@fest-lib/fl-ui 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/assets/OPFS.uniform.worker-Ddx6J_37.js +2982 -0
- package/dist/fl-ui.js +16004 -0
- package/dist/font-registry-BWosB92f.js +271 -0
- package/package.json +104 -0
- package/src/styles/font-loader.ts +224 -0
- package/src/styles/font-registry.ts +275 -0
- package/src/styles/fonts/_index.scss +8 -0
- package/src/styles/fonts/_inter.scss +171 -0
- package/src/styles/index.scss +2 -0
- package/src/styles/index.ts +33 -0
- package/src/styles/layers.scss +1 -0
- package/src/styles/patch-global-native-controls.scss +13 -0
- package/src/styles/scripts/encode-fonts.ts +172 -0
- package/src/styles/skins/thin/Thin.ts +13 -0
- package/src/styles/ui/_bar.scss +271 -0
- package/src/styles/ui/_buttons.scss +215 -0
- package/src/styles/ui/_color.scss +3 -0
- package/src/styles/ui/_colorize.scss +5 -0
- package/src/styles/ui/_content.scss +169 -0
- package/src/styles/ui/_essentials-options.scss +2 -0
- package/src/styles/ui/_essentials.scss +705 -0
- package/src/styles/ui/_explorer-content.scss +362 -0
- package/src/styles/ui/_explorer.scss +237 -0
- package/src/styles/ui/_forms-bare-host-elements.scss +25 -0
- package/src/styles/ui/_forms-options.scss +2 -0
- package/src/styles/ui/_forms.scss +280 -0
- package/src/styles/ui/_forms_misc.scss +201 -0
- package/src/styles/ui/_gridbox.scss +298 -0
- package/src/styles/ui/_home-host.scss +179 -0
- package/src/styles/ui/_index.scss +22 -0
- package/src/styles/ui/_launcher-typography.scss +31 -0
- package/src/styles/ui/_layers.scss +48 -0
- package/src/styles/ui/_layout.scss +3 -0
- package/src/styles/ui/_markdown.scss +1636 -0
- package/src/styles/ui/_modal.scss +258 -0
- package/src/styles/ui/_motion.scss +3 -0
- package/src/styles/ui/_native-host-button-chrome.scss +31 -0
- package/src/styles/ui/_orientation-functions.scss +274 -0
- package/src/styles/ui/_orientbox.scss +97 -0
- package/src/styles/ui/_scrollbar.scss +257 -0
- package/src/styles/ui/_shared-overlays.scss +16 -0
- package/src/styles/ui/_sidebar.scss +477 -0
- package/src/styles/ui/_speed-dial.scss +47 -0
- package/src/styles/ui/_tables.scss +28 -0
- package/src/styles/ui/_tabs.scss +406 -0
- package/src/styles/ui/_taskbar.scss +215 -0
- package/src/styles/ui/_toolbars.scss +165 -0
- package/src/styles/ui/_typography.scss +11 -0
- package/src/styles/ui/_utils.scss +8 -0
- package/src/styles/ui/_variables.scss +45 -0
- package/src/styles/ui/_viewport.scss +469 -0
- package/src/styles/ui/_window-frame.scss +658 -0
- package/src/styles/ui/home-host-apply.scss +10 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inter Font Family Styles
|
|
3
|
+
*
|
|
4
|
+
* Style declarations for Inter font family (not loading directly)
|
|
5
|
+
* Fonts are loaded via JavaScript font-loader module
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* Fallback fonts: */
|
|
9
|
+
:root, :host, :scope {
|
|
10
|
+
font-family: Inter, sans-serif;
|
|
11
|
+
font-optical-sizing: auto;
|
|
12
|
+
font-variation-settings: "opsz" 16;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Variable fonts usage: */
|
|
16
|
+
@supports (font-variation-settings: normal) {
|
|
17
|
+
:root, :host, :scope {
|
|
18
|
+
font-family: InterVariable, sans-serif;
|
|
19
|
+
font-optical-sizing: auto;
|
|
20
|
+
font-variation-settings: "opsz" 16;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Font feature values: */
|
|
25
|
+
@font-feature-values InterVariable {
|
|
26
|
+
@character-variant {
|
|
27
|
+
cv01: 1;
|
|
28
|
+
cv02: 2;
|
|
29
|
+
cv03: 3;
|
|
30
|
+
cv04: 4;
|
|
31
|
+
cv05: 5;
|
|
32
|
+
cv06: 6;
|
|
33
|
+
cv07: 7;
|
|
34
|
+
cv08: 8;
|
|
35
|
+
cv09: 9;
|
|
36
|
+
cv10: 10;
|
|
37
|
+
cv11: 11;
|
|
38
|
+
cv12: 12;
|
|
39
|
+
cv13: 13;
|
|
40
|
+
alt-1: 1; /* Alternate one */
|
|
41
|
+
alt-3: 9; /* Flat-top three */
|
|
42
|
+
open-4: 2; /* Open four */
|
|
43
|
+
open-6: 3; /* Open six */
|
|
44
|
+
open-9: 4; /* Open nine */
|
|
45
|
+
lc-l-with-tail: 5; /* Lower-case L with tail */
|
|
46
|
+
simplified-u: 6; /* Simplified u */
|
|
47
|
+
alt-double-s: 7; /* Alternate German double s */
|
|
48
|
+
uc-i-with-serif: 8; /* Upper-case i with serif */
|
|
49
|
+
uc-g-with-spur: 10; /* Capital G with spur */
|
|
50
|
+
single-story-a: 11; /* Single-story a */
|
|
51
|
+
compact-lc-f: 12; /* Compact f */
|
|
52
|
+
compact-lc-t: 13; /* Compact t */
|
|
53
|
+
}
|
|
54
|
+
@styleset {
|
|
55
|
+
ss01: 1;
|
|
56
|
+
ss02: 2;
|
|
57
|
+
ss03: 3;
|
|
58
|
+
ss04: 4;
|
|
59
|
+
ss05: 5;
|
|
60
|
+
ss06: 6;
|
|
61
|
+
ss07: 7;
|
|
62
|
+
ss08: 8;
|
|
63
|
+
open-digits: 1; /* Open digits */
|
|
64
|
+
disambiguation: 2; /* Disambiguation (with zero) */
|
|
65
|
+
disambiguation-except-zero: 4; /* Disambiguation (no zero) */
|
|
66
|
+
round-quotes-and-commas: 3; /* Round quotes & commas */
|
|
67
|
+
square-punctuation: 7; /* Square punctuation */
|
|
68
|
+
square-quotes: 8; /* Square quotes */
|
|
69
|
+
circled-characters: 5; /* Circled characters */
|
|
70
|
+
squared-characters: 6; /* Squared characters */
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@font-feature-values Inter {
|
|
75
|
+
@character-variant {
|
|
76
|
+
cv01: 1;
|
|
77
|
+
cv02: 2;
|
|
78
|
+
cv03: 3;
|
|
79
|
+
cv04: 4;
|
|
80
|
+
cv05: 5;
|
|
81
|
+
cv06: 6;
|
|
82
|
+
cv07: 7;
|
|
83
|
+
cv08: 8;
|
|
84
|
+
cv09: 9;
|
|
85
|
+
cv10: 10;
|
|
86
|
+
cv11: 11;
|
|
87
|
+
cv12: 12;
|
|
88
|
+
cv13: 13;
|
|
89
|
+
alt-1: 1; /* Alternate one */
|
|
90
|
+
alt-3: 9; /* Flat-top three */
|
|
91
|
+
open-4: 2; /* Open four */
|
|
92
|
+
open-6: 3; /* Open six */
|
|
93
|
+
open-9: 4; /* Open nine */
|
|
94
|
+
lc-l-with-tail: 5; /* Lower-case L with tail */
|
|
95
|
+
simplified-u: 6; /* Simplified u */
|
|
96
|
+
alt-double-s: 7; /* Alternate German double s */
|
|
97
|
+
uc-i-with-serif: 8; /* Upper-case i with serif */
|
|
98
|
+
uc-g-with-spur: 10; /* Capital G with spur */
|
|
99
|
+
single-story-a: 11; /* Single-story a */
|
|
100
|
+
compact-lc-f: 12; /* Compact f */
|
|
101
|
+
compact-lc-t: 13; /* Compact t */
|
|
102
|
+
}
|
|
103
|
+
@styleset {
|
|
104
|
+
ss01: 1;
|
|
105
|
+
ss02: 2;
|
|
106
|
+
ss03: 3;
|
|
107
|
+
ss04: 4;
|
|
108
|
+
ss05: 5;
|
|
109
|
+
ss06: 6;
|
|
110
|
+
ss07: 7;
|
|
111
|
+
ss08: 8;
|
|
112
|
+
open-digits: 1; /* Open digits */
|
|
113
|
+
disambiguation: 2; /* Disambiguation (with zero) */
|
|
114
|
+
disambiguation-except-zero: 4; /* Disambiguation (no zero) */
|
|
115
|
+
round-quotes-and-commas: 3; /* Round quotes & commas */
|
|
116
|
+
square-punctuation: 7; /* Square punctuation */
|
|
117
|
+
square-quotes: 8; /* Square quotes */
|
|
118
|
+
circled-characters: 5; /* Circled characters */
|
|
119
|
+
squared-characters: 6; /* Squared characters */
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@font-feature-values InterDisplay {
|
|
124
|
+
@character-variant {
|
|
125
|
+
cv01: 1;
|
|
126
|
+
cv02: 2;
|
|
127
|
+
cv03: 3;
|
|
128
|
+
cv04: 4;
|
|
129
|
+
cv05: 5;
|
|
130
|
+
cv06: 6;
|
|
131
|
+
cv07: 7;
|
|
132
|
+
cv08: 8;
|
|
133
|
+
cv09: 9;
|
|
134
|
+
cv10: 10;
|
|
135
|
+
cv11: 11;
|
|
136
|
+
cv12: 12;
|
|
137
|
+
cv13: 13;
|
|
138
|
+
alt-1: 1; /* Alternate one */
|
|
139
|
+
alt-3: 9; /* Flat-top three */
|
|
140
|
+
open-4: 2; /* Open four */
|
|
141
|
+
open-6: 3; /* Open six */
|
|
142
|
+
open-9: 4; /* Open nine */
|
|
143
|
+
lc-l-with-tail: 5; /* Lower-case L with tail */
|
|
144
|
+
simplified-u: 6; /* Simplified u */
|
|
145
|
+
alt-double-s: 7; /* Alternate German double s */
|
|
146
|
+
uc-i-with-serif: 8; /* Upper-case i with serif */
|
|
147
|
+
uc-g-with-spur: 10; /* Capital G with spur */
|
|
148
|
+
single-story-a: 11; /* Single-story a */
|
|
149
|
+
compact-lc-f: 12; /* Compact f */
|
|
150
|
+
compact-lc-t: 13; /* Compact t */
|
|
151
|
+
}
|
|
152
|
+
@styleset {
|
|
153
|
+
ss01: 1;
|
|
154
|
+
ss02: 2;
|
|
155
|
+
ss03: 3;
|
|
156
|
+
ss04: 4;
|
|
157
|
+
ss05: 5;
|
|
158
|
+
ss06: 6;
|
|
159
|
+
ss07: 7;
|
|
160
|
+
ss08: 8;
|
|
161
|
+
open-digits: 1; /* Open digits */
|
|
162
|
+
disambiguation: 2; /* Disambiguation (with zero) */
|
|
163
|
+
disambiguation-except-zero: 4; /* Disambiguation (no zero) */
|
|
164
|
+
round-quotes-and-commas: 3; /* Round quotes & commas */
|
|
165
|
+
square-punctuation: 7; /* Square punctuation */
|
|
166
|
+
square-quotes: 8; /* Square quotes */
|
|
167
|
+
circled-characters: 5; /* Circled characters */
|
|
168
|
+
squared-characters: 6; /* Squared characters */
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Veela.CSS TypeScript Module
|
|
3
|
+
*
|
|
4
|
+
* Exports font loading utilities and type definitions.
|
|
5
|
+
* Runtime styles and initialization are in ../scss/runtime/index.ts
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { loadAllFonts, loadFontRegistry } from './font-loader';
|
|
9
|
+
import { loadAsAdopted } from '@fest-lib/dom'; //@ts-ignore
|
|
10
|
+
import styles from './index.scss?inline';
|
|
11
|
+
import globalNativeControlStyles from './patch-global-native-controls.scss?inline';
|
|
12
|
+
|
|
13
|
+
//
|
|
14
|
+
const fontStyles = `
|
|
15
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
//
|
|
19
|
+
export * from './font-loader';
|
|
20
|
+
export type { FontMetadata } from './font-loader';
|
|
21
|
+
export const loader = async (options?: { includeGlobalNativeControls?: boolean }) => {
|
|
22
|
+
await loadAsAdopted(fontStyles)?.catch(() => undefined);
|
|
23
|
+
await loadAllFonts().catch(() => undefined);
|
|
24
|
+
await loadAsAdopted(styles)?.catch(() => undefined);
|
|
25
|
+
if (options?.includeGlobalNativeControls) {
|
|
26
|
+
await loadAsAdopted(globalNativeControlStyles)?.catch(() => undefined);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Host-wide native control chrome (legacy). Prefer scoping with `.btn` / field mixins. */
|
|
31
|
+
export async function loadFlUIGlobalNativeControlStyles(): Promise<void> {
|
|
32
|
+
await loadAsAdopted(globalNativeControlStyles)?.catch(() => undefined);
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer tokens, base, layout, utilities, shells, shell, views, view, viewer, components, ux-layer, markdown, essentials, print, print-breaks, overrides;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Incremental sheet: legacy host-wide native `button` + bare `input`/`select`/`textarea`.
|
|
2
|
+
@use "./ui/native-host-button-chrome" as host;
|
|
3
|
+
@use "./ui/forms-bare-host-elements" as bare;
|
|
4
|
+
|
|
5
|
+
@layer tokens, base, layout, utilities, shells, shell, views, view, viewer, components, ux-layer, markdown, essentials, print, print-breaks, overrides;
|
|
6
|
+
|
|
7
|
+
@layer components {
|
|
8
|
+
button {
|
|
9
|
+
@include host.essentials-native-host-button-chrome-base;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@include bare.emit-bare-form-element-layer();
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Font Encoding Utility
|
|
4
|
+
*
|
|
5
|
+
* Standalone script to compress fonts and encode them to base64
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFile, writeFile, mkdir, readdir } from 'node:fs/promises';
|
|
9
|
+
import { resolve, dirname, basename, extname } from 'node:path';
|
|
10
|
+
import { createReadStream, createWriteStream } from 'node:fs';
|
|
11
|
+
import { pipeline } from 'node:stream/promises';
|
|
12
|
+
import { createGzip } from 'node:zlib';
|
|
13
|
+
|
|
14
|
+
interface FontMetadata {
|
|
15
|
+
base64: string;
|
|
16
|
+
family: string;
|
|
17
|
+
style: string;
|
|
18
|
+
weight: string | number;
|
|
19
|
+
compressed: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function encodeToBase64(filePath: string): Promise<string> {
|
|
23
|
+
const data = await readFile(filePath);
|
|
24
|
+
return data.toString('base64');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function compressFile(inputPath: string, outputPath: string): Promise<void> {
|
|
28
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
29
|
+
const readStream = createReadStream(inputPath);
|
|
30
|
+
const writeStream = createWriteStream(outputPath);
|
|
31
|
+
const gzipStream = createGzip({ level: 9 });
|
|
32
|
+
await pipeline(readStream, gzipStream, writeStream);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parseFontMetadata(filename: string): {
|
|
36
|
+
family: string;
|
|
37
|
+
style: string;
|
|
38
|
+
weight: string | number;
|
|
39
|
+
} {
|
|
40
|
+
const baseName = basename(filename, extname(filename));
|
|
41
|
+
let family = 'Inter';
|
|
42
|
+
let style = 'normal';
|
|
43
|
+
let weight: string | number = 'normal';
|
|
44
|
+
|
|
45
|
+
if (baseName.includes('InterVariable')) {
|
|
46
|
+
family = 'InterVariable';
|
|
47
|
+
weight = '100 900';
|
|
48
|
+
if (baseName.includes('Italic')) style = 'italic';
|
|
49
|
+
} else if (baseName.includes('InterDisplay')) {
|
|
50
|
+
family = 'InterDisplay';
|
|
51
|
+
const weightMatch = baseName.match(/(Thin|ExtraLight|Light|Regular|Medium|SemiBold|Bold|ExtraBold|Black)/);
|
|
52
|
+
if (weightMatch) {
|
|
53
|
+
const weightMap: Record<string, number> = {
|
|
54
|
+
'Thin': 100, 'ExtraLight': 200, 'Light': 300, 'Regular': 400,
|
|
55
|
+
'Medium': 500, 'SemiBold': 600, 'Bold': 700, 'ExtraBold': 800, 'Black': 900
|
|
56
|
+
};
|
|
57
|
+
weight = weightMap[weightMatch[1]] || 400;
|
|
58
|
+
}
|
|
59
|
+
if (baseName.includes('Italic')) style = 'italic';
|
|
60
|
+
} else if (baseName.startsWith('Inter-')) {
|
|
61
|
+
family = 'Inter';
|
|
62
|
+
const weightMatch = baseName.match(/(Thin|ExtraLight|Light|Regular|Medium|SemiBold|Bold|ExtraBold|Black)/);
|
|
63
|
+
if (weightMatch) {
|
|
64
|
+
const weightMap: Record<string, number> = {
|
|
65
|
+
'Thin': 100, 'ExtraLight': 200, 'Light': 300, 'Regular': 400,
|
|
66
|
+
'Medium': 500, 'SemiBold': 600, 'Bold': 700, 'ExtraBold': 800, 'Black': 900
|
|
67
|
+
};
|
|
68
|
+
weight = weightMap[weightMatch[1]] || 400;
|
|
69
|
+
}
|
|
70
|
+
if (baseName.includes('Italic')) style = 'italic';
|
|
71
|
+
}
|
|
72
|
+
return { family, style, weight };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function scanFontDirectory(dir: string): Promise<string[]> {
|
|
76
|
+
const fontFiles: string[] = [];
|
|
77
|
+
const scanDir = async (currentDir: string) => {
|
|
78
|
+
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
const fullPath = resolve(currentDir, entry.name);
|
|
81
|
+
if (entry.isDirectory()) {
|
|
82
|
+
await scanDir(fullPath);
|
|
83
|
+
} else if (entry.isFile() && (entry.name.endsWith('.woff2') || entry.name.endsWith('.woff'))) {
|
|
84
|
+
fontFiles.push(fullPath);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
await scanDir(dir);
|
|
89
|
+
return fontFiles;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function encodeFonts(fontDir: string, outputFile: string, compress: boolean = false): Promise<void> {
|
|
93
|
+
console.log(`[font-encoder] Scanning font directory: ${fontDir}`);
|
|
94
|
+
const fontFiles = await scanFontDirectory(fontDir);
|
|
95
|
+
console.log(`[font-encoder] Found ${fontFiles.length} font files`);
|
|
96
|
+
|
|
97
|
+
if (fontFiles.length === 0) {
|
|
98
|
+
console.warn('[font-encoder] No font files found!');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const generatedFonts: Array<{ key: string; metadata: FontMetadata }> = [];
|
|
103
|
+
|
|
104
|
+
for (const fontPath of fontFiles) {
|
|
105
|
+
const relativePath = fontPath.replace(resolve(fontDir) + '/', '');
|
|
106
|
+
const metadata = parseFontMetadata(fontPath);
|
|
107
|
+
console.log(`[font-encoder] Processing: ${relativePath}`);
|
|
108
|
+
|
|
109
|
+
let base64: string;
|
|
110
|
+
let isCompressed = false;
|
|
111
|
+
|
|
112
|
+
if (fontPath.endsWith('.woff2')) {
|
|
113
|
+
base64 = await encodeToBase64(fontPath);
|
|
114
|
+
isCompressed = false;
|
|
115
|
+
} else if (compress && !fontPath.endsWith('.woff2')) {
|
|
116
|
+
const tempPath = fontPath + '.gz';
|
|
117
|
+
await compressFile(fontPath, tempPath);
|
|
118
|
+
base64 = await encodeToBase64(tempPath);
|
|
119
|
+
isCompressed = true;
|
|
120
|
+
const { unlink } = await import('node:fs/promises');
|
|
121
|
+
await unlink(tempPath);
|
|
122
|
+
} else {
|
|
123
|
+
base64 = await encodeToBase64(fontPath);
|
|
124
|
+
isCompressed = false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const key = relativePath.replace(/[\/\\]/g, '_').replace(/\.(woff2?|gz)$/i, '');
|
|
128
|
+
generatedFonts.push({
|
|
129
|
+
key,
|
|
130
|
+
metadata: { base64, family: metadata.family, style: metadata.style, weight: metadata.weight, compressed: isCompressed }
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const registryContent = `/**
|
|
135
|
+
* Font Registry
|
|
136
|
+
* Auto-generated by font encoding utility
|
|
137
|
+
* DO NOT EDIT MANUALLY
|
|
138
|
+
* Generated: ${new Date().toISOString()}
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
export const fontRegistry: Record<string, any> = {
|
|
142
|
+
${generatedFonts.map(({ key, metadata }) => ` '${key}': {
|
|
143
|
+
base64: '${metadata.base64}',
|
|
144
|
+
family: '${metadata.family}',
|
|
145
|
+
style: '${metadata.style}',
|
|
146
|
+
weight: ${typeof metadata.weight === 'string' ? `'${metadata.weight}'` : metadata.weight},
|
|
147
|
+
compressed: ${metadata.compressed}
|
|
148
|
+
}`).join(',\n')}
|
|
149
|
+
};
|
|
150
|
+
`;
|
|
151
|
+
|
|
152
|
+
await mkdir(dirname(outputFile), { recursive: true });
|
|
153
|
+
await writeFile(outputFile, registryContent, 'utf-8');
|
|
154
|
+
|
|
155
|
+
console.log(`[font-encoder] Generated font registry with ${generatedFonts.length} fonts`);
|
|
156
|
+
console.log(`[font-encoder] Output file: ${outputFile}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const __dirname = resolve(import.meta.dirname, '../');
|
|
160
|
+
const fontDir = resolve(__dirname, './assets/fonts');
|
|
161
|
+
const outputFile = resolve(__dirname, './src/ts/font-registry.ts');
|
|
162
|
+
const compress = process.argv.includes('--compress');
|
|
163
|
+
|
|
164
|
+
encodeFonts(fontDir, outputFile, compress)
|
|
165
|
+
.then(() => {
|
|
166
|
+
console.log('[font-encoder] Done!');
|
|
167
|
+
process.exit(0);
|
|
168
|
+
})
|
|
169
|
+
.catch((error) => {
|
|
170
|
+
console.error('[font-encoder] Error:', error);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DOMMixin } from "@fest-lib/dom";
|
|
2
|
+
|
|
3
|
+
//
|
|
4
|
+
export class ThinSlider extends DOMMixin {
|
|
5
|
+
constructor(name?: string) { super(name); }
|
|
6
|
+
|
|
7
|
+
connect(_self: unknown) {
|
|
8
|
+
// TODO: implement thin slider connection logic
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
//
|
|
13
|
+
new ThinSlider("slider-thin");
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
|
|
2
|
+
@use "veela-lib" as *;
|
|
3
|
+
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Bar Component Styles
|
|
6
|
+
// ============================================================================
|
|
7
|
+
@mixin tabbed-bar($selector: ".bar") {
|
|
8
|
+
@at-root :host {
|
|
9
|
+
|
|
10
|
+
// ================================================================
|
|
11
|
+
// Slotted Bar Content
|
|
12
|
+
// ================================================================
|
|
13
|
+
&::slotted([slot="bar"]), ::slotted([slot="bar"]) {
|
|
14
|
+
// Grid positioning
|
|
15
|
+
grid-column: 1 / -1;
|
|
16
|
+
grid-row: 1 / -1;
|
|
17
|
+
|
|
18
|
+
// Sizing
|
|
19
|
+
inline-size: stretch;
|
|
20
|
+
block-size: stretch;
|
|
21
|
+
max-block-size: 3rem;
|
|
22
|
+
flex-grow: 1;
|
|
23
|
+
|
|
24
|
+
// Alignment
|
|
25
|
+
place-content: center;
|
|
26
|
+
place-items: center;
|
|
27
|
+
|
|
28
|
+
//
|
|
29
|
+
background-color: transparent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//
|
|
33
|
+
#{$selector} {
|
|
34
|
+
// ================================================================
|
|
35
|
+
// Base Layout
|
|
36
|
+
// ================================================================
|
|
37
|
+
& {
|
|
38
|
+
display: grid;
|
|
39
|
+
grid-template-columns:
|
|
40
|
+
[sidebar-col] minmax(0px, 0px)
|
|
41
|
+
[button-col] minmax(0px, 3.5rem)
|
|
42
|
+
[content-col] minmax(0px, 1fr)
|
|
43
|
+
[pinned-col] minmax(0px, 3.5rem);
|
|
44
|
+
grid-template-rows: minmax(0px, 1fr);
|
|
45
|
+
grid-auto-rows: 0;
|
|
46
|
+
|
|
47
|
+
// Grid positioning
|
|
48
|
+
grid-column: 1 / -1;
|
|
49
|
+
grid-row: bar-row;
|
|
50
|
+
z-index: 3;
|
|
51
|
+
border-radius: 0px;
|
|
52
|
+
|
|
53
|
+
// Sizing
|
|
54
|
+
inline-size: stretch;
|
|
55
|
+
block-size: stretch;
|
|
56
|
+
min-block-size: stretch;
|
|
57
|
+
max-block-size: 3.5rem;
|
|
58
|
+
box-sizing: border-box;
|
|
59
|
+
|
|
60
|
+
// Spacing
|
|
61
|
+
padding-block: 0.25rem;
|
|
62
|
+
padding-inline: 0.75rem;
|
|
63
|
+
gap: 0px;
|
|
64
|
+
|
|
65
|
+
// Visual
|
|
66
|
+
box-shadow: none;
|
|
67
|
+
overflow: hidden;
|
|
68
|
+
|
|
69
|
+
// Interaction
|
|
70
|
+
pointer-events: auto;
|
|
71
|
+
background-color: oklch(from --c2-surface(0.15, var(--current, currentColor)) l c h / 0.9);
|
|
72
|
+
backdrop-filter: blur(1rem);
|
|
73
|
+
filter: none;
|
|
74
|
+
|
|
75
|
+
// Alignment
|
|
76
|
+
place-content: center;
|
|
77
|
+
place-items: center;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ================================================================
|
|
81
|
+
// Child Elements
|
|
82
|
+
// ================================================================
|
|
83
|
+
& > :where(*) {
|
|
84
|
+
grid-row: 1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ================================================================
|
|
88
|
+
// Spacing by Tab Position
|
|
89
|
+
// ================================================================
|
|
90
|
+
@at-root :host & {
|
|
91
|
+
margin-block-start: 0px;
|
|
92
|
+
margin-block-end: var(--space-md);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@at-root :host([tab-position="bottom"]) & {
|
|
96
|
+
margin-block-start: var(--space-md);
|
|
97
|
+
margin-block-end: 0px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@at-root :host([tab-position="top"]) & {
|
|
101
|
+
margin-block-start: 0px;
|
|
102
|
+
margin-block-end: var(--space-md);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//
|
|
106
|
+
.toolbar-slot {
|
|
107
|
+
padding: 0rem;
|
|
108
|
+
grid-row: 1 / 1 span;
|
|
109
|
+
grid-column: content-col;
|
|
110
|
+
max-inline-size: stretch;
|
|
111
|
+
max-block-size: 3rem;
|
|
112
|
+
inline-size: stretch;
|
|
113
|
+
block-size: stretch;
|
|
114
|
+
min-inline-size: 0px;
|
|
115
|
+
min-block-size: 3rem;
|
|
116
|
+
place-content: center;
|
|
117
|
+
place-items: center;
|
|
118
|
+
justify-content: center;
|
|
119
|
+
align-items: center;
|
|
120
|
+
gap: 0rem;
|
|
121
|
+
margin: 0px;
|
|
122
|
+
inset: 0px;
|
|
123
|
+
z-index: 99;
|
|
124
|
+
border-radius: 50cqmin;
|
|
125
|
+
overflow: hidden;
|
|
126
|
+
opacity: 0;
|
|
127
|
+
visibility: hidden;
|
|
128
|
+
pointer-events: none;
|
|
129
|
+
transition: opacity var(--duration-normal, 160ms) var(--ease-out, ease),
|
|
130
|
+
visibility var(--duration-normal, 160ms) var(--ease-out, ease);
|
|
131
|
+
|
|
132
|
+
//
|
|
133
|
+
&[toolbar-opened="true"] {
|
|
134
|
+
opacity: 1;
|
|
135
|
+
visibility: visible;
|
|
136
|
+
pointer-events: auto;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ================================================================
|
|
141
|
+
// Sidebar Toggle Button
|
|
142
|
+
// ================================================================
|
|
143
|
+
button.open-sidebar {
|
|
144
|
+
display: flex;
|
|
145
|
+
flex-direction: row;
|
|
146
|
+
align-items: center;
|
|
147
|
+
justify-content: center;
|
|
148
|
+
place-content: center;
|
|
149
|
+
place-items: center;
|
|
150
|
+
gap: 0rem;
|
|
151
|
+
margin-inline-end: var(--space-sm);
|
|
152
|
+
|
|
153
|
+
// Grid positioning
|
|
154
|
+
grid-column: button-col;
|
|
155
|
+
grid-row: 1;
|
|
156
|
+
|
|
157
|
+
// Sizing
|
|
158
|
+
aspect-ratio: 1 / 1;
|
|
159
|
+
inline-size: fit-content;
|
|
160
|
+
block-size: stretch;
|
|
161
|
+
min-inline-size: 3rem;
|
|
162
|
+
min-block-size: 3rem;
|
|
163
|
+
max-inline-size: 3rem;
|
|
164
|
+
box-sizing: border-box;
|
|
165
|
+
padding: 0.25rem;
|
|
166
|
+
|
|
167
|
+
// Visual
|
|
168
|
+
background-color: transparent;
|
|
169
|
+
border: 0px none transparent;
|
|
170
|
+
outline: 0px none transparent;
|
|
171
|
+
border-radius: 50cqmin;
|
|
172
|
+
transition: background-color var(--duration-normal, 160ms) var(--ease-out, ease);
|
|
173
|
+
|
|
174
|
+
// Interaction
|
|
175
|
+
cursor: pointer;
|
|
176
|
+
pointer-events: auto;
|
|
177
|
+
touch-action: pan-x;
|
|
178
|
+
|
|
179
|
+
// Colorization
|
|
180
|
+
background-color: --c2-surface(var(--_color-shade), var(--current, currentColor));
|
|
181
|
+
|
|
182
|
+
// Icon
|
|
183
|
+
ui-icon {
|
|
184
|
+
inline-size: var(--tabbed-icon-size);
|
|
185
|
+
block-size: var(--tabbed-icon-size);
|
|
186
|
+
min-inline-size: var(--tabbed-icon-size);
|
|
187
|
+
min-block-size: var(--tabbed-icon-size);
|
|
188
|
+
max-inline-size: var(--tabbed-icon-size);
|
|
189
|
+
max-block-size: var(--tabbed-icon-size);
|
|
190
|
+
aspect-ratio: 1 / 1;
|
|
191
|
+
flex-shrink: 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Label
|
|
195
|
+
span {
|
|
196
|
+
display: block;
|
|
197
|
+
font-size: 0.8rem;
|
|
198
|
+
font-weight: 400;
|
|
199
|
+
padding-inline-end: 0.333rem;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Focus state
|
|
203
|
+
&:focus-visible {
|
|
204
|
+
outline: 2px solid color-mix(in oklch, currentColor 35%, transparent);
|
|
205
|
+
outline-offset: 2px;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ================================================================
|
|
210
|
+
// Tab Buttons
|
|
211
|
+
// ================================================================
|
|
212
|
+
:where(.ui-tabbed-box-tab) button {
|
|
213
|
+
padding: 0.5rem;
|
|
214
|
+
touch-action: pan-x;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ================================================================
|
|
218
|
+
// Handle (hidden)
|
|
219
|
+
// ================================================================
|
|
220
|
+
.ui-tabbed-box-handle {
|
|
221
|
+
inline-size: 0;
|
|
222
|
+
block-size: 0;
|
|
223
|
+
visibility: hidden;
|
|
224
|
+
pointer-events: none;
|
|
225
|
+
place-content: center;
|
|
226
|
+
place-items: center;
|
|
227
|
+
overflow: visible;
|
|
228
|
+
touch-action: pan-x;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ================================================================
|
|
232
|
+
// Icons
|
|
233
|
+
// ================================================================
|
|
234
|
+
ui-icon {
|
|
235
|
+
content-visibility: visible;
|
|
236
|
+
pointer-events: none;
|
|
237
|
+
color: --c2-on-surface(0.0, var(--current, currentColor));
|
|
238
|
+
--icon-color: --c2-on-surface(0.0, var(--current, currentColor));
|
|
239
|
+
inline-size: var(--tabbed-icon-size);
|
|
240
|
+
block-size: var(--tabbed-icon-size);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ================================================================
|
|
244
|
+
// Alignment by Tab Position
|
|
245
|
+
// ================================================================
|
|
246
|
+
@at-root :host([tab-position="bottom"]) #{$selector} & {
|
|
247
|
+
align-self: end;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ================================================================
|
|
251
|
+
// Responsive Behavior
|
|
252
|
+
// ================================================================
|
|
253
|
+
// Drop menu mode: always show button
|
|
254
|
+
@at-root :host([sidebar-drop-menu]) & {
|
|
255
|
+
button.open-sidebar {
|
|
256
|
+
display: flex !important;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Desktop: hide button when sidebar is not in drop menu mode
|
|
261
|
+
@at-root :host(:not([sidebar-drop-menu])) & {
|
|
262
|
+
@container (min-inline-size: 800px) {
|
|
263
|
+
--button-inline-size: 0px;
|
|
264
|
+
& button.open-sidebar {
|
|
265
|
+
display: none;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|