feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit de2d83092e
28274 changed files with 3816354 additions and 90 deletions

View File

@@ -0,0 +1,80 @@
import SVGGraphicsElement from '../svg-graphics-element/SVGGraphicsElement.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import SVGAnimatedLength from '../../svg/SVGAnimatedLength.js';
import SVGAnimatedEnumeration from '../../svg/SVGAnimatedEnumeration.js';
import SVGPoint from '../../svg/SVGPoint.js';
import SVGRect from '../../svg/SVGRect.js';
/**
* SVG Text Content Element.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/SVGTextContentElement
*/
export default class SVGTextContentElement extends SVGGraphicsElement {
static readonly LENGTHADJUST_UNKNOWN = 0;
static readonly LENGTHADJUST_SPACING = 1;
static readonly LENGTHADJUST_SPACINGANDGLYPHS = 2;
[PropertySymbol.textLength]: SVGAnimatedLength | null;
[PropertySymbol.lengthAdjust]: SVGAnimatedEnumeration | null;
/**
* Returns textLength.
*
* @returns Text length.
*/
get textLength(): SVGAnimatedLength;
/**
* Returns lengthAdjust.
*
* @returns Length adjust.
*/
get lengthAdjust(): SVGAnimatedEnumeration;
/**
* Returns the number of characters available for rendering.
*
* @returns Number of characters.
*/
getNumberOfChars(): number;
/**
* Returns a float representing the computed length for the text within the element.
*
* @returns Computed text length.
*/
getComputedTextLength(): number;
/**
* Returns a float representing the computed length of the formatted text advance distance for a substring of text within the element. Note that this method only accounts for the widths of the glyphs in the substring and any extra spacing inserted by the CSS 'letter-spacing' and 'word-spacing' properties. Visual spacing adjustments made by the 'x' attribute is ignored.
*
* @param _charnum The index of the first character in the substring.
* @param _nchars The number of characters in the substring.
*/
getSubStringLength(_charnum: number, _nchars: number): number;
/**
* Returns a SVGPoint representing the position of a typographic character after text layout has been performed.
*
* @param _charnum The index of the character.
*/
getStartPositionOfChar(_charnum: number): SVGPoint;
/**
* Returns a SVGPoint representing the trailing position of a typographic character after text layout has been performed.
*
* @param _charnum The index of the character.
*/
getEndPositionOfChar(_charnum: number): SVGPoint;
/**
* Returns a SVGRect representing the computed tight bounding box of the glyph cell that corresponds to a given typographic character.
*
* @param _charnum The index of the character.
*/
getExtentOfChar(_charnum: number): SVGRect;
/**
* Returns a float representing the rotation of typographic character.
*
* @param _charnum The index of the character.
*/
getRotationOfChar(_charnum: number): number;
/**
* Returns a long representing the character which caused a text glyph to be rendered at a given position in the coordinate system. Because the relationship between characters and glyphs is not one-to-one, only the first character of the relevant typographic character is returned
*
* @param _point The point to be tested.
*/
getCharNumAtPosition(_point: SVGPoint): number;
}
//# sourceMappingURL=SVGTextContentElement.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"SVGTextContentElement.d.ts","sourceRoot":"","sources":["../../../src/nodes/svg-text-content-element/SVGTextContentElement.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,+CAA+C,CAAC;AAC/E,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAC1D,OAAO,iBAAiB,MAAM,gCAAgC,CAAC;AAC/D,OAAO,sBAAsB,MAAM,qCAAqC,CAAC;AACzE,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAC7C,OAAO,OAAO,MAAM,sBAAsB,CAAC;AAE3C;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,kBAAkB;IAEpE,gBAAuB,oBAAoB,KAAK;IAChD,gBAAuB,oBAAoB,KAAK;IAChD,gBAAuB,6BAA6B,KAAK;IAGlD,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IAC7D,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAQ;IAE3E;;;;OAIG;IACH,IAAW,UAAU,IAAI,iBAAiB,CAYzC;IAED;;;;OAIG;IACH,IAAW,YAAY,IAAI,sBAAsB,CAchD;IAED;;;;OAIG;IACI,gBAAgB,IAAI,MAAM;IAKjC;;;;OAIG;IACI,qBAAqB,IAAI,MAAM;IAKtC;;;;;OAKG;IACI,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAKpE;;;;OAIG;IACI,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;IAKzD;;;;OAIG;IACI,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;IAKvD;;;;OAIG;IACI,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKjD;;;;OAIG;IACI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAKlD;;;;OAIG;IACI,oBAAoB,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM;CAIrD"}

View File

@@ -0,0 +1,124 @@
import SVGGraphicsElement from '../svg-graphics-element/SVGGraphicsElement.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import SVGAnimatedLength from '../../svg/SVGAnimatedLength.js';
import SVGAnimatedEnumeration from '../../svg/SVGAnimatedEnumeration.js';
import SVGPoint from '../../svg/SVGPoint.js';
import SVGRect from '../../svg/SVGRect.js';
/**
* SVG Text Content Element.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/SVGTextContentElement
*/
export default class SVGTextContentElement extends SVGGraphicsElement {
// Public static properties
static LENGTHADJUST_UNKNOWN = 0;
static LENGTHADJUST_SPACING = 1;
static LENGTHADJUST_SPACINGANDGLYPHS = 2;
// Internal properties
[PropertySymbol.textLength] = null;
[PropertySymbol.lengthAdjust] = null;
/**
* Returns textLength.
*
* @returns Text length.
*/
get textLength() {
if (!this[PropertySymbol.textLength]) {
this[PropertySymbol.textLength] = new SVGAnimatedLength(PropertySymbol.illegalConstructor, this[PropertySymbol.window], {
getAttribute: () => this.getAttribute('textLength'),
setAttribute: (value) => this.setAttribute('textLength', value)
});
}
return this[PropertySymbol.textLength];
}
/**
* Returns lengthAdjust.
*
* @returns Length adjust.
*/
get lengthAdjust() {
if (!this[PropertySymbol.lengthAdjust]) {
this[PropertySymbol.lengthAdjust] = new SVGAnimatedEnumeration(PropertySymbol.illegalConstructor, this[PropertySymbol.window], {
getAttribute: () => this.getAttribute('lengthAdjust'),
setAttribute: (value) => this.setAttribute('lengthAdjust', value),
values: ['spacing', 'spacingAndGlyphs'],
defaultValue: 'spacing'
});
}
return this[PropertySymbol.lengthAdjust];
}
/**
* Returns the number of characters available for rendering.
*
* @returns Number of characters.
*/
getNumberOfChars() {
// TODO: Implement.
return 0;
}
/**
* Returns a float representing the computed length for the text within the element.
*
* @returns Computed text length.
*/
getComputedTextLength() {
// TODO: Implement.
return 0;
}
/**
* Returns a float representing the computed length of the formatted text advance distance for a substring of text within the element. Note that this method only accounts for the widths of the glyphs in the substring and any extra spacing inserted by the CSS 'letter-spacing' and 'word-spacing' properties. Visual spacing adjustments made by the 'x' attribute is ignored.
*
* @param _charnum The index of the first character in the substring.
* @param _nchars The number of characters in the substring.
*/
getSubStringLength(_charnum, _nchars) {
// TODO: Implement.
return 0;
}
/**
* Returns a SVGPoint representing the position of a typographic character after text layout has been performed.
*
* @param _charnum The index of the character.
*/
getStartPositionOfChar(_charnum) {
// TODO: Implement.
return new SVGPoint(PropertySymbol.illegalConstructor, this[PropertySymbol.window]);
}
/**
* Returns a SVGPoint representing the trailing position of a typographic character after text layout has been performed.
*
* @param _charnum The index of the character.
*/
getEndPositionOfChar(_charnum) {
// TODO: Implement.
return new SVGPoint(PropertySymbol.illegalConstructor, this[PropertySymbol.window]);
}
/**
* Returns a SVGRect representing the computed tight bounding box of the glyph cell that corresponds to a given typographic character.
*
* @param _charnum The index of the character.
*/
getExtentOfChar(_charnum) {
// TODO: Implement.
return new SVGRect(PropertySymbol.illegalConstructor, this[PropertySymbol.window]);
}
/**
* Returns a float representing the rotation of typographic character.
*
* @param _charnum The index of the character.
*/
getRotationOfChar(_charnum) {
// TODO: Implement.
return 0;
}
/**
* Returns a long representing the character which caused a text glyph to be rendered at a given position in the coordinate system. Because the relationship between characters and glyphs is not one-to-one, only the first character of the relevant typographic character is returned
*
* @param _point The point to be tested.
*/
getCharNumAtPosition(_point) {
// TODO: Implement.
return 0;
}
}
//# sourceMappingURL=SVGTextContentElement.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"SVGTextContentElement.js","sourceRoot":"","sources":["../../../src/nodes/svg-text-content-element/SVGTextContentElement.ts"],"names":[],"mappings":"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"}