@desktalk/ui 0.1.0-alpha.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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chart-entry.d.ts +7 -0
  3. package/dist/chart-entry.d.ts.map +1 -0
  4. package/dist/chart.umd.js +30 -0
  5. package/dist/chart.umd.js.map +7 -0
  6. package/dist/desktalk-ui.js +1681 -0
  7. package/dist/desktalk-ui.js.map +7 -0
  8. package/dist/dt-badge.d.ts +39 -0
  9. package/dist/dt-badge.d.ts.map +1 -0
  10. package/dist/dt-badge.stories.d.ts +34 -0
  11. package/dist/dt-badge.stories.d.ts.map +1 -0
  12. package/dist/dt-button.d.ts +51 -0
  13. package/dist/dt-button.d.ts.map +1 -0
  14. package/dist/dt-button.stories.d.ts +40 -0
  15. package/dist/dt-button.stories.d.ts.map +1 -0
  16. package/dist/dt-card.d.ts +30 -0
  17. package/dist/dt-card.d.ts.map +1 -0
  18. package/dist/dt-card.stories.d.ts +31 -0
  19. package/dist/dt-card.stories.d.ts.map +1 -0
  20. package/dist/dt-chart.d.ts +67 -0
  21. package/dist/dt-chart.d.ts.map +1 -0
  22. package/dist/dt-chart.stories.d.ts +26 -0
  23. package/dist/dt-chart.stories.d.ts.map +1 -0
  24. package/dist/dt-divider.d.ts +41 -0
  25. package/dist/dt-divider.d.ts.map +1 -0
  26. package/dist/dt-divider.stories.d.ts +38 -0
  27. package/dist/dt-divider.stories.d.ts.map +1 -0
  28. package/dist/dt-grid.d.ts +50 -0
  29. package/dist/dt-grid.d.ts.map +1 -0
  30. package/dist/dt-grid.stories.d.ts +49 -0
  31. package/dist/dt-grid.stories.d.ts.map +1 -0
  32. package/dist/dt-list-view.d.ts +94 -0
  33. package/dist/dt-list-view.d.ts.map +1 -0
  34. package/dist/dt-list-view.stories.d.ts +49 -0
  35. package/dist/dt-list-view.stories.d.ts.map +1 -0
  36. package/dist/dt-markdown-editor.d.ts +54 -0
  37. package/dist/dt-markdown-editor.d.ts.map +1 -0
  38. package/dist/dt-markdown-editor.stories.d.ts +22 -0
  39. package/dist/dt-markdown-editor.stories.d.ts.map +1 -0
  40. package/dist/dt-markdown.d.ts +47 -0
  41. package/dist/dt-markdown.d.ts.map +1 -0
  42. package/dist/dt-markdown.stories.d.ts +22 -0
  43. package/dist/dt-markdown.stories.d.ts.map +1 -0
  44. package/dist/dt-select.d.ts +71 -0
  45. package/dist/dt-select.d.ts.map +1 -0
  46. package/dist/dt-select.stories.d.ts +41 -0
  47. package/dist/dt-select.stories.d.ts.map +1 -0
  48. package/dist/dt-stack.d.ts +51 -0
  49. package/dist/dt-stack.d.ts.map +1 -0
  50. package/dist/dt-stack.stories.d.ts +48 -0
  51. package/dist/dt-stack.stories.d.ts.map +1 -0
  52. package/dist/dt-stat.d.ts +61 -0
  53. package/dist/dt-stat.d.ts.map +1 -0
  54. package/dist/dt-stat.stories.d.ts +47 -0
  55. package/dist/dt-stat.stories.d.ts.map +1 -0
  56. package/dist/dt-table-view.d.ts +119 -0
  57. package/dist/dt-table-view.d.ts.map +1 -0
  58. package/dist/dt-table-view.stories.d.ts +46 -0
  59. package/dist/dt-table-view.stories.d.ts.map +1 -0
  60. package/dist/dt-tooltip.d.ts +47 -0
  61. package/dist/dt-tooltip.d.ts.map +1 -0
  62. package/dist/dt-tooltip.stories.d.ts +41 -0
  63. package/dist/dt-tooltip.stories.d.ts.map +1 -0
  64. package/dist/index.d.ts +23 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +1681 -0
  67. package/dist/index.js.map +7 -0
  68. package/dist/lib/chart-loader.d.ts +10 -0
  69. package/dist/lib/chart-loader.d.ts.map +1 -0
  70. package/dist/lib/marked-loader.d.ts +13 -0
  71. package/dist/lib/marked-loader.d.ts.map +1 -0
  72. package/dist/lib/milkdown-loader.d.ts +12 -0
  73. package/dist/lib/milkdown-loader.d.ts.map +1 -0
  74. package/dist/lib/template-bind.d.ts +3 -0
  75. package/dist/lib/template-bind.d.ts.map +1 -0
  76. package/dist/lib/virtualizer.d.ts +35 -0
  77. package/dist/lib/virtualizer.d.ts.map +1 -0
  78. package/dist/marked-entry.d.ts +7 -0
  79. package/dist/marked-entry.d.ts.map +1 -0
  80. package/dist/marked.umd.js +61 -0
  81. package/dist/marked.umd.js.map +7 -0
  82. package/dist/milkdown-entry.d.ts +7 -0
  83. package/dist/milkdown-entry.d.ts.map +1 -0
  84. package/dist/milkdown.umd.js +1875 -0
  85. package/dist/milkdown.umd.js.map +7 -0
  86. package/dist/stores/all-components.stories.d.ts +6 -0
  87. package/dist/stores/all-components.stories.d.ts.map +1 -0
  88. package/dist/theme-css.d.ts +38 -0
  89. package/dist/theme-css.d.ts.map +1 -0
  90. package/dist/theme-css.js +193 -0
  91. package/dist/theme-css.js.map +7 -0
  92. package/dist/ui-elements.d.ts +213 -0
  93. package/dist/ui-elements.d.ts.map +1 -0
  94. package/package.json +65 -0
  95. package/src/fonts/OFL.txt +76 -0
  96. package/src/fonts/README.md +43 -0
  97. package/src/fonts/fonts.css +91 -0
  98. package/src/fonts/sora-400.ttf +0 -0
  99. package/src/fonts/sora-500.ttf +0 -0
  100. package/src/fonts/sora-600.ttf +0 -0
  101. package/src/fonts/sora-700.ttf +0 -0
  102. package/src/fonts/work-sans-400.ttf +0 -0
  103. package/src/fonts/work-sans-500.ttf +0 -0
  104. package/src/fonts/work-sans-600.ttf +0 -0
  105. package/src/fonts/work-sans-700.ttf +0 -0
  106. package/src/theme-css.ts +390 -0
  107. package/types.d.ts +249 -0
@@ -0,0 +1,390 @@
1
+ /**
2
+ * Shared theme CSS generator — works in both Node.js (server) and browser (frontend).
3
+ *
4
+ * Produces the full `:root { --dt-* }` CSS token block from an accent color and
5
+ * theme mode. Uses `culori` for hex→OKLCH conversion; all other logic is pure math.
6
+ *
7
+ * This module has NO DOM dependency.
8
+ */
9
+ import { converter, parse } from 'culori';
10
+
11
+ export type ThemeMode = 'light' | 'dark';
12
+
13
+ export interface ThemePreferences {
14
+ accentColor: string;
15
+ theme: ThemeMode;
16
+ }
17
+
18
+ const DEFAULT_ACCENT_COLOR = '#7c6ff7';
19
+
20
+ const toOklch = converter('oklch');
21
+
22
+ const SCALE: Array<[string, number, number]> = [
23
+ ['50', 0.98, 0.005],
24
+ ['100', 0.94, 0.01],
25
+ ['150', 0.88, 0.015],
26
+ ['200', 0.8, 0.02],
27
+ ['300', 0.7, 0.025],
28
+ ['400', 0.6, 0.03],
29
+ ['500', 0.5, 0.04],
30
+ ['600', 0.4, 0.03],
31
+ ['700', 0.32, 0.025],
32
+ ['800', 0.24, 0.03],
33
+ ['850', 0.2, 0.035],
34
+ ['900', 0.16, 0.04],
35
+ ['950', 0.12, 0.05],
36
+ ];
37
+
38
+ const STATUS_HUES = {
39
+ danger: 25,
40
+ success: 155,
41
+ warning: 80,
42
+ info: 250,
43
+ } as const;
44
+
45
+ export const DEFAULT_THEME_PREFERENCES: ThemePreferences = {
46
+ accentColor: DEFAULT_ACCENT_COLOR,
47
+ theme: 'dark',
48
+ };
49
+
50
+ function clamp(value: number, min: number, max: number): number {
51
+ return Math.min(Math.max(value, min), max);
52
+ }
53
+
54
+ function wrapHue(value: number): number {
55
+ const wrapped = value % 360;
56
+ return wrapped < 0 ? wrapped + 360 : wrapped;
57
+ }
58
+
59
+ function formatNumber(value: number): string {
60
+ return value
61
+ .toFixed(3)
62
+ .replace(/\.0+$/, '')
63
+ .replace(/(\.\d*?)0+$/, '$1');
64
+ }
65
+
66
+ function oklchValue(lightness: number, chroma: number, hue: number, alpha?: number): string {
67
+ const base = `oklch(${formatNumber(clamp(lightness, 0, 1))} ${formatNumber(clamp(chroma, 0, 0.4))} ${formatNumber(wrapHue(hue))}`;
68
+ return alpha === undefined ? `${base})` : `${base} / ${formatNumber(clamp(alpha, 0, 1))})`;
69
+ }
70
+
71
+ function normalizeMode(value: string | undefined): ThemeMode {
72
+ return value === 'dark' ? 'dark' : 'light';
73
+ }
74
+
75
+ function getAccentOklch(accentColor: string): { l: number; c: number; h: number } {
76
+ const parsed = parse(accentColor) ?? parse(DEFAULT_ACCENT_COLOR);
77
+ const converted = parsed ? toOklch(parsed) : null;
78
+
79
+ if (!converted) {
80
+ return { l: 0.623, c: 0.234, h: 286 };
81
+ }
82
+
83
+ return {
84
+ l: clamp(converted.l ?? 0.623, 0, 1),
85
+ c: clamp(converted.c ?? 0.234, 0, 0.37),
86
+ h: wrapHue(converted.h ?? 286),
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Generate the full `:root { --dt-* }` CSS text for the given theme preferences.
92
+ *
93
+ * This is the single source of truth for the DeskTalk color system.
94
+ */
95
+ export function generateThemeCSS(preferences: ThemePreferences): string {
96
+ const mode = normalizeMode(preferences.theme);
97
+ const dark = mode === 'dark';
98
+ const { l, c, h } = getAccentOklch(preferences.accentColor);
99
+ const lines: string[] = [];
100
+ const put = (name: string, value: string | number) => {
101
+ lines.push(` ${name}: ${value};`);
102
+ };
103
+ const scaleVar = (name: string) => `var(--dt-scale-${name})`;
104
+
105
+ put('--dt-accent-h', formatNumber(h));
106
+ put('--dt-accent-c', formatNumber(c));
107
+ put('--dt-accent-l', formatNumber(l));
108
+ put('--dt-mode-sign', dark ? '1' : '-1');
109
+
110
+ for (const [name, lightness, chroma] of SCALE) {
111
+ put(`--dt-scale-${name}`, oklchValue(lightness, chroma, h));
112
+ }
113
+
114
+ put('--dt-bg', dark ? scaleVar('950') : scaleVar('50'));
115
+ put('--dt-bg-subtle', dark ? scaleVar('900') : scaleVar('100'));
116
+ put('--dt-surface', dark ? scaleVar('850') : scaleVar('100'));
117
+ put('--dt-surface-hover', dark ? scaleVar('800') : scaleVar('150'));
118
+ put('--dt-surface-active', dark ? scaleVar('700') : scaleVar('200'));
119
+ put('--dt-overlay', dark ? oklchValue(0.16, 0.04, h, 0.85) : oklchValue(0.98, 0.005, h, 0.85));
120
+
121
+ put('--dt-text', dark ? scaleVar('50') : scaleVar('950'));
122
+ put('--dt-text-secondary', dark ? scaleVar('300') : scaleVar('600'));
123
+ put('--dt-text-muted', dark ? scaleVar('400') : scaleVar('500'));
124
+
125
+ put('--dt-border', dark ? scaleVar('800') : scaleVar('200'));
126
+ put(
127
+ '--dt-border-subtle',
128
+ dark ? oklchValue(0.2, 0.035, h, 0.6) : oklchValue(0.88, 0.015, h, 0.6),
129
+ );
130
+ put('--dt-border-strong', dark ? scaleVar('700') : scaleVar('300'));
131
+
132
+ const accentHoverShift = dark ? 0.05 : -0.05;
133
+ const accentActiveShift = dark ? 0.1 : -0.1;
134
+ put('--dt-accent', oklchValue(l, c, h));
135
+ put('--dt-accent-hover', oklchValue(l + accentHoverShift, c, h));
136
+ put('--dt-accent-active', oklchValue(l + accentActiveShift, c, h));
137
+ put('--dt-accent-subtle', oklchValue(l, c, h, 0.15));
138
+ put('--dt-accent-ghost', oklchValue(l, c, h, 0.08));
139
+ put('--dt-text-on-accent', l > 0.6 ? scaleVar('950') : scaleVar('50'));
140
+
141
+ for (const [name, hue] of Object.entries(STATUS_HUES)) {
142
+ const lightness = dark ? 0.7 : 0.45;
143
+ put(`--dt-${name}`, oklchValue(lightness, 0.18, hue));
144
+ put(`--dt-${name}-subtle`, oklchValue(lightness, 0.18, hue, 0.15));
145
+ }
146
+
147
+ put('--dt-dock-bg', 'var(--dt-overlay)');
148
+ put('--dt-actions-bar-bg', 'var(--dt-bg-subtle)');
149
+ put('--dt-window-chrome', 'var(--dt-surface)');
150
+ put('--dt-window-body', 'var(--dt-bg)');
151
+ put('--dt-info-panel-bg', 'var(--dt-bg-subtle)');
152
+ put(
153
+ '--dt-wallpaper',
154
+ dark
155
+ ? `linear-gradient(135deg, ${oklchValue(0.25, 0.08, h)} 0%, ${oklchValue(0.3, 0.1, h)} 50%, ${oklchValue(0.4, 0.04, h + 30)} 100%)`
156
+ : `linear-gradient(135deg, ${oklchValue(0.85, 0.06, h)} 0%, ${oklchValue(0.8, 0.08, h)} 50%, ${oklchValue(0.75, 0.03, h + 30)} 100%)`,
157
+ );
158
+
159
+ put('--dt-glass', dark ? oklchValue(0.2, 0.035, h, 0.7) : oklchValue(0.94, 0.01, h, 0.7));
160
+ put(
161
+ '--dt-glass-border',
162
+ dark ? oklchValue(0.98, 0.005, h, 0.1) : oklchValue(0.12, 0.05, h, 0.12),
163
+ );
164
+ put(
165
+ '--dt-glass-highlight',
166
+ dark ? oklchValue(0.98, 0.005, h, 0.05) : oklchValue(0.98, 0.005, h, 0.45),
167
+ );
168
+ put('--dt-shadow-color', dark ? oklchValue(0.12, 0.05, h, 0.4) : oklchValue(0.12, 0.05, h, 0.15));
169
+
170
+ // Font variables
171
+ put('--font-display', "'Sora', system-ui, -apple-system, sans-serif");
172
+ put('--font-ui', "'Work Sans', system-ui, -apple-system, sans-serif");
173
+ put('--font-mono', "'SF Mono', 'Fira Code', 'Fira Mono', Menlo, Consolas, monospace");
174
+
175
+ return `:root {\n${lines.join('\n')}\n}`;
176
+ }
177
+
178
+ /**
179
+ * Base stylesheet for AI-generated HTML.
180
+ *
181
+ * Provides sensible defaults for body, headings, tables, cards, buttons, and
182
+ * code blocks — all using semantic `--dt-*` tokens. This ensures generated HTML
183
+ * looks native to DeskTalk without the AI needing to emit its own reset/base styles.
184
+ */
185
+ /**
186
+ * Font face definitions for self-hosted Google Fonts.
187
+ * Include this in your HTML <head> before theme CSS.
188
+ */
189
+ export const FONT_FACES_CSS = `
190
+ /* Sora - Display font for headings and decorative numbers */
191
+ @font-face {
192
+ font-family: 'Sora';
193
+ font-style: normal;
194
+ font-weight: 400;
195
+ font-display: swap;
196
+ src: url('sora-400.ttf') format('truetype');
197
+ }
198
+ @font-face {
199
+ font-family: 'Sora';
200
+ font-style: normal;
201
+ font-weight: 500;
202
+ font-display: swap;
203
+ src: url('sora-500.ttf') format('truetype');
204
+ }
205
+ @font-face {
206
+ font-family: 'Sora';
207
+ font-style: normal;
208
+ font-weight: 600;
209
+ font-display: swap;
210
+ src: url('sora-600.ttf') format('truetype');
211
+ }
212
+ @font-face {
213
+ font-family: 'Sora';
214
+ font-style: normal;
215
+ font-weight: 700;
216
+ font-display: swap;
217
+ src: url('sora-700.ttf') format('truetype');
218
+ }
219
+
220
+ /* Work Sans - UI font for body text and buttons */
221
+ @font-face {
222
+ font-family: 'Work Sans';
223
+ font-style: normal;
224
+ font-weight: 400;
225
+ font-display: swap;
226
+ src: url('work-sans-400.ttf') format('truetype');
227
+ }
228
+ @font-face {
229
+ font-family: 'Work Sans';
230
+ font-style: normal;
231
+ font-weight: 500;
232
+ font-display: swap;
233
+ src: url('work-sans-500.ttf') format('truetype');
234
+ }
235
+ @font-face {
236
+ font-family: 'Work Sans';
237
+ font-style: normal;
238
+ font-weight: 600;
239
+ font-display: swap;
240
+ src: url('work-sans-600.ttf') format('truetype');
241
+ }
242
+ @font-face {
243
+ font-family: 'Work Sans';
244
+ font-style: normal;
245
+ font-weight: 700;
246
+ font-display: swap;
247
+ src: url('work-sans-700.ttf') format('truetype');
248
+ }
249
+ `.trim();
250
+
251
+ /**
252
+ * CSS variables for font families.
253
+ */
254
+ export const FONT_VARIABLES_CSS = `
255
+ :root {
256
+ --font-display: 'Sora', system-ui, -apple-system, sans-serif;
257
+ --font-ui: 'Work Sans', system-ui, -apple-system, sans-serif;
258
+ --font-mono: 'SF Mono', 'Fira Code', 'Fira Mono', Menlo, Consolas, monospace;
259
+ }
260
+ `.trim();
261
+
262
+ export const HTML_FORM_CONTROLS_STYLESHEET = `
263
+ input[type="text"], input[type="email"], input[type="password"], input[type="number"], input[type="search"], input[type="url"] {
264
+ font-family: var(--font-mono, 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace);
265
+ font-size: 0.8125rem;
266
+ font-weight: 600;
267
+ letter-spacing: 0.04em;
268
+ line-height: 1;
269
+ color: var(--dt-text);
270
+ background: var(--dt-surface);
271
+ border: 1px solid var(--dt-accent);
272
+ border-radius: 2px;
273
+ padding: 6px 10px;
274
+ outline: none;
275
+ width: 100%;
276
+ box-sizing: border-box;
277
+ transition: all 0.1s ease;
278
+ position: relative;
279
+ }
280
+ input[type="text"]:hover, input[type="email"]:hover, input[type="password"]:hover, input[type="number"]:hover, input[type="search"]:hover, input[type="url"]:hover {
281
+ background: var(--dt-accent);
282
+ color: var(--dt-text-on-accent);
283
+ }
284
+ input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="url"]:focus {
285
+ background: var(--dt-accent);
286
+ color: var(--dt-text-on-accent);
287
+ }
288
+ input[type="text"]:disabled, input[type="email"]:disabled, input[type="password"]:disabled, input[type="number"]:disabled, input[type="search"]:disabled, input[type="url"]:disabled {
289
+ cursor: not-allowed;
290
+ opacity: 0.4;
291
+ }
292
+ input[type="text"]::placeholder, input[type="email"]::placeholder, input[type="password"]::placeholder, input[type="number"]::placeholder, input[type="search"]::placeholder, input[type="url"]::placeholder {
293
+ color: var(--dt-text-muted);
294
+ font-weight: 600;
295
+ letter-spacing: 0.04em;
296
+ }
297
+ `.trim();
298
+
299
+ /**
300
+ * Base stylesheet for AI-generated HTML.
301
+ *
302
+ * Provides sensible defaults for body, headings, tables, cards, buttons, and
303
+ * code blocks — all using semantic `--dt-*` tokens. This ensures generated HTML
304
+ * looks native to DeskTalk without the AI needing to emit its own reset/base styles.
305
+ */
306
+ export const HTML_BASE_STYLESHEET = `
307
+ * { margin: 0; padding: 0; box-sizing: border-box; }
308
+ body {
309
+ font-family: var(--font-ui, 'Work Sans'), system-ui, -apple-system, sans-serif;
310
+ background: var(--dt-bg);
311
+ color: var(--dt-text);
312
+ line-height: 1.5;
313
+ padding: 16px;
314
+ -webkit-font-smoothing: antialiased;
315
+ -moz-osx-font-smoothing: grayscale;
316
+ }
317
+ h1, h2, h3, h4, h5, h6 {
318
+ font-family: var(--font-display, 'Sora'), system-ui, -apple-system, sans-serif !important;
319
+ color: var(--dt-text) !important;
320
+ line-height: 1.2 !important;
321
+ margin-top: 0 !important;
322
+ margin-bottom: 0.5em !important;
323
+ font-style: normal !important;
324
+ text-transform: none !important;
325
+ letter-spacing: -0.02em !important;
326
+ }
327
+ h1 { font-size: 1.5rem !important; font-weight: 500 !important; letter-spacing: -0.03em !important; }
328
+ h2 { font-size: 1.25rem !important; font-weight: 500 !important; letter-spacing: -0.02em !important; }
329
+ h3 { font-size: 1.125rem !important; font-weight: 500 !important; }
330
+ h4 { font-size: 1rem !important; font-weight: 500 !important; }
331
+ h5 { font-size: 0.875rem !important; font-weight: 500 !important; }
332
+ h6 { font-size: 0.75rem !important; font-weight: 600 !important; text-transform: uppercase !important; letter-spacing: 0.1em !important; }
333
+ p {
334
+ font-family: var(--font-ui, 'Work Sans'), system-ui, -apple-system, sans-serif !important;
335
+ font-size: 0.9375rem !important;
336
+ font-weight: 400 !important;
337
+ line-height: 1.5 !important;
338
+ color: var(--dt-text-secondary) !important;
339
+ margin-top: 0 !important;
340
+ margin-bottom: 1em !important;
341
+ }
342
+ a { color: var(--dt-accent); text-decoration: none; font-weight: 500; }
343
+ a:hover { color: var(--dt-accent-hover); text-decoration: none; }
344
+ hr {
345
+ border: none;
346
+ border-top: 1px solid var(--dt-border);
347
+ margin: 1.25em 0;
348
+ }
349
+ table {
350
+ width: 100%;
351
+ border-collapse: collapse;
352
+ margin-bottom: 1em;
353
+ font-size: 0.875rem;
354
+ }
355
+ th, td {
356
+ padding: 10px 12px;
357
+ text-align: left;
358
+ border-bottom: 1px solid var(--dt-border);
359
+ }
360
+ th {
361
+ background: var(--dt-surface);
362
+ color: var(--dt-text);
363
+ font-weight: 500;
364
+ font-size: 0.8125rem;
365
+ letter-spacing: 0.01em;
366
+ }
367
+ tr:hover td { background: var(--dt-surface-hover); }
368
+ code {
369
+ font-family: 'SF Mono', 'Fira Code', 'Fira Mono', Menlo, Consolas, monospace;
370
+ background: var(--dt-surface);
371
+ padding: 2px 6px;
372
+ border-radius: 4px;
373
+ font-size: 0.8125em;
374
+ font-weight: 400;
375
+ }
376
+ pre {
377
+ background: var(--dt-surface);
378
+ border: 1px solid var(--dt-border);
379
+ border-radius: 6px;
380
+ padding: 14px;
381
+ overflow-x: auto;
382
+ margin-bottom: 1em;
383
+ font-size: 0.8125rem;
384
+ }
385
+ pre code { background: none; padding: 0; }
386
+ .text-muted { color: var(--dt-text-muted); }
387
+ .text-secondary { color: var(--dt-text-secondary); }
388
+ .accent-bg { background: var(--dt-accent-subtle); }
389
+ ${HTML_FORM_CONTROLS_STYLESHEET}
390
+ `.trim();
package/types.d.ts ADDED
@@ -0,0 +1,249 @@
1
+ import type * as React from 'react';
2
+
3
+ export {};
4
+
5
+ type DtTooltipAttributes = Partial<{
6
+ content: string;
7
+ placement: 'top' | 'bottom' | 'left' | 'right';
8
+ delay: number | string;
9
+ disabled: boolean;
10
+ class: string;
11
+ style: string | Record<string, string>;
12
+ }>;
13
+
14
+ type DtTooltipJSXProps = DtTooltipAttributes & {
15
+ children?: unknown;
16
+ ref?: unknown;
17
+ key?: string | number | null;
18
+ };
19
+
20
+ type DtCardAttributes = Partial<{
21
+ variant: 'default' | 'outlined' | 'filled';
22
+ class: string;
23
+ style: string | Record<string, string>;
24
+ }>;
25
+
26
+ type DtCardJSXProps = DtCardAttributes & {
27
+ children?: unknown;
28
+ ref?: unknown;
29
+ key?: string | number | null;
30
+ };
31
+
32
+ type DtSelectAttributes = Partial<{
33
+ id: string;
34
+ value: string;
35
+ options: Array<{ value: string; label: string }>;
36
+ placeholder: string;
37
+ disabled: boolean;
38
+ align: 'left' | 'right';
39
+ 'ondt-change': (event: CustomEvent<{ value: string }>) => void;
40
+ class: string;
41
+ style: string | Record<string, string>;
42
+ }>;
43
+
44
+ type DtSelectJSXProps = DtSelectAttributes & {
45
+ children?: unknown;
46
+ ref?: unknown;
47
+ key?: string | number | null;
48
+ };
49
+
50
+ type DtGridAttributes = Partial<{
51
+ cols: '1' | '2' | '3' | '4' | '5' | '6';
52
+ gap: '0' | '4' | '8' | '12' | '16' | '20' | '24' | '32';
53
+ 'min-width': '150' | '180' | '200' | '220' | '260' | '300';
54
+ class: string;
55
+ style: string | Record<string, string>;
56
+ }>;
57
+
58
+ type DtGridJSXProps = DtGridAttributes & {
59
+ children?: unknown;
60
+ ref?: unknown;
61
+ key?: string | number | null;
62
+ };
63
+
64
+ type DtStackAttributes = Partial<{
65
+ direction: 'column' | 'row';
66
+ gap: '0' | '4' | '8' | '12' | '16' | '20' | '24' | '32';
67
+ align: 'start' | 'center' | 'end' | 'stretch';
68
+ class: string;
69
+ style: string | Record<string, string>;
70
+ }>;
71
+
72
+ type DtStackJSXProps = DtStackAttributes & {
73
+ children?: unknown;
74
+ ref?: unknown;
75
+ key?: string | number | null;
76
+ };
77
+
78
+ type DtStatAttributes = Partial<{
79
+ label: string;
80
+ value: string;
81
+ description: string;
82
+ size: 'sm' | 'md' | 'lg';
83
+ variant: 'default' | 'outlined' | 'filled';
84
+ trend: 'up' | 'down' | 'neutral';
85
+ 'trend-value': string;
86
+ class: string;
87
+ style: string | Record<string, string>;
88
+ }>;
89
+
90
+ type DtStatJSXProps = DtStatAttributes & {
91
+ children?: unknown;
92
+ ref?: unknown;
93
+ key?: string | number | null;
94
+ };
95
+
96
+ type DtBadgeAttributes = Partial<{
97
+ variant: 'accent' | 'success' | 'danger' | 'warning' | 'info' | 'default' | 'neutral';
98
+ size: 'sm' | 'md' | 'lg';
99
+ text: string;
100
+ class: string;
101
+ style: string | Record<string, string>;
102
+ }>;
103
+
104
+ type DtBadgeJSXProps = DtBadgeAttributes & {
105
+ children?: unknown;
106
+ ref?: unknown;
107
+ key?: string | number | null;
108
+ };
109
+
110
+ type DtButtonAttributes = Partial<{
111
+ variant: 'primary' | 'secondary' | 'ghost' | 'danger';
112
+ size: 'sm' | 'md' | 'lg';
113
+ disabled: boolean;
114
+ fullwidth: boolean;
115
+ type: 'button' | 'submit' | 'reset';
116
+ class: string;
117
+ style: string | Record<string, string>;
118
+ }>;
119
+
120
+ type DtButtonJSXProps = DtButtonAttributes & {
121
+ children?: unknown;
122
+ onClick?: React.MouseEventHandler<HTMLElement>;
123
+ ref?: unknown;
124
+ key?: string | number | null;
125
+ };
126
+
127
+ type DtDividerAttributes = Partial<{
128
+ direction: 'horizontal' | 'vertical';
129
+ 'style-variant': 'default' | 'subtle' | 'strong';
130
+ spacing: 'sm' | 'md' | 'lg';
131
+ class: string;
132
+ style: string | Record<string, string>;
133
+ }>;
134
+
135
+ type DtDividerJSXProps = DtDividerAttributes & {
136
+ children?: unknown;
137
+ ref?: unknown;
138
+ key?: string | number | null;
139
+ };
140
+
141
+ type DtListViewAttributes = Partial<{
142
+ 'item-height': number | string;
143
+ dividers: boolean;
144
+ selectable: 'none' | 'single' | 'multi';
145
+ 'empty-text': string;
146
+ class: string;
147
+ style: string | Record<string, string>;
148
+ }>;
149
+
150
+ type DtListViewJSXProps = DtListViewAttributes & {
151
+ children?: unknown;
152
+ ref?: unknown;
153
+ key?: string | number | null;
154
+ };
155
+
156
+ type DtTableViewAttributes = Partial<{
157
+ 'row-height': number | string;
158
+ sortable: boolean;
159
+ striped: boolean;
160
+ bordered: boolean;
161
+ 'empty-text': string;
162
+ class: string;
163
+ style: string | Record<string, string>;
164
+ }>;
165
+
166
+ type DtTableViewJSXProps = DtTableViewAttributes & {
167
+ children?: unknown;
168
+ ref?: unknown;
169
+ key?: string | number | null;
170
+ };
171
+
172
+ type DtColumnAttributes = Partial<{
173
+ field: string;
174
+ header: string;
175
+ width: string;
176
+ 'min-width': string;
177
+ align: 'left' | 'center' | 'right';
178
+ class: string;
179
+ style: string | Record<string, string>;
180
+ }>;
181
+
182
+ type DtColumnJSXProps = DtColumnAttributes & {
183
+ children?: unknown;
184
+ ref?: unknown;
185
+ key?: string | number | null;
186
+ };
187
+
188
+ type DtChartAttributes = Partial<{
189
+ type: 'bar' | 'line' | 'area' | 'pie' | 'doughnut' | 'radar' | 'scatter' | 'bubble';
190
+ legend: 'top' | 'bottom' | 'left' | 'right' | 'none';
191
+ stacked: boolean;
192
+ labels: string;
193
+ class: string;
194
+ style: string | Record<string, string>;
195
+ }>;
196
+
197
+ type DtChartJSXProps = DtChartAttributes & {
198
+ children?: unknown;
199
+ ref?: unknown;
200
+ key?: string | number | null;
201
+ };
202
+
203
+ type DtMarkdownAttributes = Partial<{
204
+ streaming: boolean;
205
+ 'unsafe-html': boolean;
206
+ class: string;
207
+ style: string | Record<string, string>;
208
+ }>;
209
+
210
+ type DtMarkdownJSXProps = DtMarkdownAttributes & {
211
+ children?: unknown;
212
+ ref?: unknown;
213
+ key?: string | number | null;
214
+ };
215
+
216
+ type DtMarkdownEditorAttributes = Partial<{
217
+ placeholder: string;
218
+ readonly: boolean;
219
+ class: string;
220
+ style: string | Record<string, string>;
221
+ }>;
222
+
223
+ type DtMarkdownEditorJSXProps = DtMarkdownEditorAttributes & {
224
+ children?: unknown;
225
+ ref?: unknown;
226
+ key?: string | number | null;
227
+ };
228
+
229
+ declare module 'react' {
230
+ namespace JSX {
231
+ interface IntrinsicElements {
232
+ 'dt-tooltip': DtTooltipJSXProps;
233
+ 'dt-card': DtCardJSXProps;
234
+ 'dt-select': DtSelectJSXProps;
235
+ 'dt-grid': DtGridJSXProps;
236
+ 'dt-stack': DtStackJSXProps;
237
+ 'dt-stat': DtStatJSXProps;
238
+ 'dt-badge': DtBadgeJSXProps;
239
+ 'dt-button': DtButtonJSXProps;
240
+ 'dt-divider': DtDividerJSXProps;
241
+ 'dt-list-view': DtListViewJSXProps;
242
+ 'dt-table-view': DtTableViewJSXProps;
243
+ 'dt-column': DtColumnJSXProps;
244
+ 'dt-chart': DtChartJSXProps;
245
+ 'dt-markdown': DtMarkdownJSXProps;
246
+ 'dt-markdown-editor': DtMarkdownEditorJSXProps;
247
+ }
248
+ }
249
+ }