orbital-ds 0.9.0 → 0.10.0

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 (73) hide show
  1. package/AGENTS.md +18 -1
  2. package/components.manifest.json +388 -1
  3. package/contract.json +5 -0
  4. package/dist/hooks/use-ds-messages.d.ts +59 -1
  5. package/dist/hooks/use-ds-messages.js +6 -0
  6. package/dist/lib/echarts-presets.d.ts +153 -0
  7. package/dist/lib/echarts-presets.js +311 -0
  8. package/dist/lib/echarts-server.d.ts +15 -0
  9. package/dist/lib/echarts-server.js +15 -0
  10. package/dist/lib/echarts-setup.d.ts +4 -0
  11. package/dist/lib/echarts-setup.js +60 -0
  12. package/dist/lib/echarts-theme.d.ts +36 -0
  13. package/dist/lib/echarts-theme.js +142 -0
  14. package/dist/lib/i18n.d.ts +57 -1
  15. package/dist/lib/i18n.js +169 -3
  16. package/dist/styles.css +43 -5
  17. package/dist/themes/friendly.css +3 -1
  18. package/dist/themes/friendly.scoped.css +3 -1
  19. package/dist/themes/friendly.tokens.json +45 -0
  20. package/dist/themes/qratia.tokens.json +49 -0
  21. package/dist/themes/tactile.css +3 -1
  22. package/dist/themes/tactile.scoped.css +3 -1
  23. package/dist/themes/tactile.tokens.json +42 -0
  24. package/dist/themes/twitter.css +3 -1
  25. package/dist/themes/twitter.scoped.css +3 -1
  26. package/dist/themes/twitter.tokens.json +45 -0
  27. package/dist/themes/zyro.css +3 -1
  28. package/dist/themes/zyro.scoped.css +3 -1
  29. package/dist/themes/zyro.tokens.json +46 -0
  30. package/dist/ui/calendar.js +4 -0
  31. package/dist/ui/code-block.d.ts +14 -0
  32. package/dist/ui/code-block.js +106 -0
  33. package/dist/ui/data-table.d.ts +185 -0
  34. package/dist/ui/data-table.js +714 -0
  35. package/dist/ui/date-picker.d.ts +65 -0
  36. package/dist/ui/date-picker.js +362 -0
  37. package/dist/ui/dropzone.d.ts +42 -0
  38. package/dist/ui/dropzone.js +220 -0
  39. package/dist/ui/echart.d.ts +31 -0
  40. package/dist/ui/echart.js +88 -0
  41. package/dist/ui/eyebrow.d.ts +7 -0
  42. package/dist/ui/eyebrow.js +16 -0
  43. package/dist/ui/filter-bar.d.ts +36 -0
  44. package/dist/ui/filter-bar.js +193 -0
  45. package/dist/ui/heatmap-grid.d.ts +39 -0
  46. package/dist/ui/heatmap-grid.js +195 -0
  47. package/dist/ui/i18n-provider.js +3 -3
  48. package/dist/ui/legend.d.ts +30 -0
  49. package/dist/ui/legend.js +124 -0
  50. package/dist/ui/notifications.d.ts +69 -0
  51. package/dist/ui/notifications.js +335 -0
  52. package/dist/ui/page-header.d.ts +19 -0
  53. package/dist/ui/page-header.js +132 -0
  54. package/dist/ui/panel.d.ts +12 -0
  55. package/dist/ui/panel.js +41 -0
  56. package/dist/ui/proportion-bar.d.ts +27 -0
  57. package/dist/ui/proportion-bar.js +92 -0
  58. package/dist/ui/sparkline.d.ts +26 -0
  59. package/dist/ui/sparkline.js +97 -0
  60. package/dist/ui/stat.d.ts +61 -0
  61. package/dist/ui/stat.js +238 -0
  62. package/dist/ui/status-badge.d.ts +38 -0
  63. package/dist/ui/status-badge.js +153 -0
  64. package/dist/ui/stepper.d.ts +20 -0
  65. package/dist/ui/stepper.js +152 -0
  66. package/dist/ui/timeline.d.ts +29 -0
  67. package/dist/ui/timeline.js +157 -0
  68. package/docs/GRAFICOS.md +125 -0
  69. package/docs/adr/0001-rtl-clases-logicas.md +78 -0
  70. package/package.json +171 -160
  71. package/scripts/doctor.mjs +0 -0
  72. package/scripts/i18n.mjs +0 -0
  73. package/scripts/init.mjs +1 -0
@@ -0,0 +1,142 @@
1
+ const PALETTE_VARS = ["--chart-1", "--chart-2", "--chart-3", "--chart-4", "--chart-5", "--info", "--success", "--warning", "--danger", "--brand"];
2
+ let ctx;
3
+ function dsResolveColor(value) {
4
+ const v = value.trim();
5
+ if (!v || typeof document === "undefined") return v;
6
+ if (ctx === void 0) {
7
+ const canvas = document.createElement("canvas");
8
+ canvas.width = canvas.height = 1;
9
+ ctx = canvas.getContext("2d", { willReadFrequently: true });
10
+ }
11
+ if (!ctx) return v;
12
+ ctx.clearRect(0, 0, 1, 1);
13
+ ctx.fillStyle = "#000";
14
+ ctx.fillStyle = v;
15
+ ctx.fillRect(0, 0, 1, 1);
16
+ const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
17
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(a / 255 * 1e3) / 1e3})`;
18
+ }
19
+ function cssColor(style, name, fallback) {
20
+ const raw = style.getPropertyValue(name).trim();
21
+ if (!raw) return fallback;
22
+ if (raw.includes("var(") && typeof document !== "undefined") {
23
+ const probe = document.createElement("span");
24
+ probe.style.color = raw;
25
+ probe.style.display = "none";
26
+ document.body.appendChild(probe);
27
+ const resolved = getComputedStyle(probe).color;
28
+ probe.remove();
29
+ return dsResolveColor(resolved || fallback);
30
+ }
31
+ return dsResolveColor(raw);
32
+ }
33
+ function dsChartTokens(el) {
34
+ const style = getComputedStyle(el ?? document.documentElement);
35
+ const c = (name, fallback) => cssColor(style, name, fallback);
36
+ const ms = (name, d) => {
37
+ const v = style.getPropertyValue(name).trim();
38
+ const n = parseFloat(v);
39
+ return Number.isNaN(n) ? d : v.endsWith("ms") ? n : n * 1e3;
40
+ };
41
+ const foreground = c("--foreground", "#1f2937");
42
+ const fontSans = style.getPropertyValue("--ds-font-sans").trim() || "system-ui, sans-serif";
43
+ return {
44
+ palette: PALETTE_VARS.map((v) => c(v, "")).filter((x, i, a) => x && a.indexOf(x) === i),
45
+ foreground,
46
+ muted: c("--muted-foreground", "#6b7280"),
47
+ border: c("--border", "#e5e7eb"),
48
+ surface: c("--popover", "#ffffff"),
49
+ surfaceForeground: c("--popover-foreground", foreground),
50
+ fontSans,
51
+ fontDisplay: style.getPropertyValue("--ds-font-display").trim() || fontSans,
52
+ motionBaseMs: ms("--ds-motion-base", 200),
53
+ motionSlowMs: ms("--ds-motion-slow", 300)
54
+ };
55
+ }
56
+ function dsChartPalette(el) {
57
+ return typeof window === "undefined" ? [] : dsChartTokens(el).palette;
58
+ }
59
+ function mix(a, b, weight) {
60
+ const parse = (s) => {
61
+ const m = s.match(/rgba?\(([^)]+)\)/);
62
+ if (m) return m[1].split(/[ ,/]+/).filter(Boolean).map(Number).slice(0, 3);
63
+ const h = s.replace("#", "");
64
+ if (/^[0-9a-f]{6}/i.test(h)) return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16));
65
+ return null;
66
+ };
67
+ const x = parse(a);
68
+ const y = parse(b);
69
+ if (!x || !y) return a;
70
+ const v = x.map((n, i) => Math.round(n * weight + y[i] * (1 - weight)));
71
+ return `rgb(${v[0]}, ${v[1]}, ${v[2]})`;
72
+ }
73
+ function dsEchartsThemeFromTokens(t, { reducedMotion = false } = {}) {
74
+ const primary = t.palette[0] ?? t.foreground;
75
+ const axis = {
76
+ axisLine: { show: true, lineStyle: { color: t.border } },
77
+ axisTick: { show: false, lineStyle: { color: t.border } },
78
+ axisLabel: { color: t.muted, fontFamily: t.fontSans },
79
+ splitLine: { show: true, lineStyle: { color: t.border, type: "dashed" } },
80
+ splitArea: { show: false },
81
+ nameTextStyle: { color: t.muted, fontFamily: t.fontSans }
82
+ };
83
+ return {
84
+ color: t.palette,
85
+ backgroundColor: "transparent",
86
+ textStyle: { fontFamily: t.fontSans, color: t.foreground },
87
+ title: {
88
+ textStyle: { color: t.foreground, fontFamily: t.fontDisplay, fontWeight: 600 },
89
+ subtextStyle: { color: t.muted, fontFamily: t.fontSans }
90
+ },
91
+ legend: { textStyle: { color: t.muted, fontFamily: t.fontSans }, inactiveColor: t.border, pageIconColor: t.foreground, pageTextStyle: { color: t.muted } },
92
+ tooltip: {
93
+ backgroundColor: t.surface,
94
+ borderColor: t.border,
95
+ borderWidth: 1,
96
+ textStyle: { color: t.surfaceForeground, fontFamily: t.fontSans },
97
+ axisPointer: { lineStyle: { color: t.muted }, crossStyle: { color: t.muted }, shadowStyle: { color: t.border } },
98
+ extraCssText: "border-radius: var(--ds-radius-popover, 12px); box-shadow: var(--ds-shadow-popover, none);"
99
+ },
100
+ categoryAxis: { ...axis, splitLine: { show: false } },
101
+ valueAxis: { ...axis, axisLine: { show: false } },
102
+ logAxis: axis,
103
+ timeAxis: { ...axis, splitLine: { show: false } },
104
+ grid: { borderColor: t.border, left: 8, right: 16, top: 32, bottom: 8 },
105
+ // ECharts 6: las etiquetas ya caben (outerBounds por defecto)
106
+ dataZoom: {
107
+ borderColor: t.border,
108
+ textStyle: { color: t.muted },
109
+ fillerColor: mix(primary, t.surface, 0.15),
110
+ handleStyle: { color: t.surface, borderColor: t.muted },
111
+ moveHandleStyle: { color: t.muted },
112
+ dataBackground: { lineStyle: { color: t.muted }, areaStyle: { color: t.border } }
113
+ },
114
+ visualMap: { textStyle: { color: t.muted }, inRange: { color: [mix(primary, t.surface, 0.12), primary] } },
115
+ line: { symbol: "circle", symbolSize: 6, smooth: false, lineStyle: { width: 2 } },
116
+ bar: { itemStyle: { borderRadius: 3 } },
117
+ pie: { itemStyle: { borderColor: t.surface, borderWidth: 2 } },
118
+ sankey: { label: { color: t.foreground, fontFamily: t.fontSans }, lineStyle: { color: "gradient", opacity: 0.35 } },
119
+ gauge: { axisLine: { lineStyle: { color: [[1, t.border]] } }, axisLabel: { color: t.muted }, detail: { color: t.foreground, fontFamily: t.fontDisplay } },
120
+ markLine: { lineStyle: { color: t.muted }, label: { color: t.muted } },
121
+ markArea: { itemStyle: { color: mix(primary, t.surface, 0.1) }, label: { color: t.muted } },
122
+ animation: !reducedMotion,
123
+ animationDuration: reducedMotion ? 0 : t.motionSlowMs,
124
+ animationDurationUpdate: reducedMotion ? 0 : t.motionBaseMs,
125
+ animationEasing: "cubicOut",
126
+ animationEasingUpdate: "cubicOut"
127
+ };
128
+ }
129
+ function dsEchartsTheme(el) {
130
+ if (typeof window === "undefined") {
131
+ return { color: [], backgroundColor: "transparent", textStyle: { fontFamily: "system-ui, sans-serif", color: "#333" } };
132
+ }
133
+ const reducedMotion = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
134
+ return dsEchartsThemeFromTokens(dsChartTokens(el), { reducedMotion });
135
+ }
136
+ export {
137
+ dsChartPalette,
138
+ dsChartTokens,
139
+ dsEchartsTheme,
140
+ dsEchartsThemeFromTokens,
141
+ dsResolveColor
142
+ };
@@ -28,6 +28,60 @@ declare const en: {
28
28
  questionnaireSkip: string;
29
29
  questionnaireNext: string;
30
30
  questionnaireSubmit: string;
31
+ codeCopy: string;
32
+ codeCopied: string;
33
+ notifications: string;
34
+ notificationsMarkAllRead: string;
35
+ notificationsEmpty: string;
36
+ notificationsUnread: string;
37
+ datePickerPlaceholder: string;
38
+ dateRangePlaceholder: string;
39
+ dropzoneTitle: string;
40
+ dropzoneHint: string;
41
+ dropzoneTooLarge: string;
42
+ dropzoneWrongType: string;
43
+ dataTableSearch: string;
44
+ dataTableColumns: string;
45
+ dataTableNoResults: string;
46
+ dataTableSelected: string;
47
+ dataTableRowsPerPage: string;
48
+ dataTablePage: string;
49
+ dataTableSortAsc: string;
50
+ dataTableSortDesc: string;
51
+ dataTableHideColumn: string;
52
+ chartExportSvg: string;
53
+ chartExportPng: string;
54
+ chartNoData: string;
55
+ stepperStep: string;
56
+ stepperCompleted: string;
57
+ stepperCurrent: string;
58
+ stepperError: string;
59
+ statIncrease: string;
60
+ statDecrease: string;
61
+ statNoChange: string;
62
+ notificationsForYou: string;
63
+ notificationsGeneral: string;
64
+ notificationsHistory: string;
65
+ datePresetToday: string;
66
+ datePresetYesterday: string;
67
+ datePresetLastDays: string;
68
+ dateApply: string;
69
+ dateClear: string;
70
+ dateMaxSpan: string;
71
+ filterAll: string;
72
+ filterClear: string;
73
+ statNoData: string;
74
+ heatmapLow: string;
75
+ heatmapHigh: string;
76
+ dataTableFilter: string;
77
+ dataTableLoading: string;
78
+ dropzoneTooMany: string;
79
+ calendarPrevious: string;
80
+ calendarNext: string;
81
+ notificationUnread: string;
82
+ statusMeaning: string;
83
+ statusCause: string;
84
+ statusAction: string;
31
85
  };
32
86
  type DsMessages = typeof en;
33
87
  type DsMessageKey = keyof DsMessages;
@@ -38,9 +92,11 @@ declare const dsCatalogs: Record<DsLocale, DsMessages>;
38
92
  * coincidencia exacta → mismo idioma base → inglés. Misma regla que la plantilla.
39
93
  */
40
94
  declare function resolveDsLocale(tag: string | null | undefined): DsLocale;
95
+ /** Rellena {marcadores} de un texto: dsFormat("{n} sin leer", { n: 3 }) → "3 sin leer". */
96
+ declare function dsFormat(text: string, vars: Record<string, string | number>): string;
41
97
  /** Textos para un idioma, con sobrescrituras opcionales. */
42
98
  declare function dsMessagesFor(tag?: string | null, overrides?: Partial<DsMessages>): DsMessages;
43
99
  declare const DS_RTL_LANGS: readonly ["ar", "he", "fa", "ur", "ps", "sd", "ug", "yi", "dv", "ckb"];
44
100
  declare function dsDirection(tag: string | null | undefined): "ltr" | "rtl";
45
101
 
46
- export { DS_DEFAULT_LOCALE, DS_LOCALES, DS_RTL_LANGS, type DsLocale, type DsMessageKey, type DsMessages, dsCatalogs, dsDirection, dsMessagesFor, resolveDsLocale };
102
+ export { DS_DEFAULT_LOCALE, DS_LOCALES, DS_RTL_LANGS, type DsLocale, type DsMessageKey, type DsMessages, dsCatalogs, dsDirection, dsFormat, dsMessagesFor, resolveDsLocale };
package/dist/lib/i18n.js CHANGED
@@ -26,7 +26,61 @@ const en = {
26
26
  questionnairePrevious: "Previous",
27
27
  questionnaireSkip: "Skip",
28
28
  questionnaireNext: "Next",
29
- questionnaireSubmit: "Submit"
29
+ questionnaireSubmit: "Submit",
30
+ codeCopy: "Copy code",
31
+ codeCopied: "Copied",
32
+ notifications: "Notifications",
33
+ notificationsMarkAllRead: "Mark all as read",
34
+ notificationsEmpty: "You're all caught up",
35
+ notificationsUnread: "{n} unread",
36
+ datePickerPlaceholder: "Pick a date",
37
+ dateRangePlaceholder: "Pick a date range",
38
+ dropzoneTitle: "Drop files here",
39
+ dropzoneHint: "or click to browse",
40
+ dropzoneTooLarge: "{name} is larger than {max}",
41
+ dropzoneWrongType: "{name} is not an accepted file type",
42
+ dataTableSearch: "Search\u2026",
43
+ dataTableColumns: "Columns",
44
+ dataTableNoResults: "No results",
45
+ dataTableSelected: "{n} of {total} selected",
46
+ dataTableRowsPerPage: "Rows per page",
47
+ dataTablePage: "Page {page} of {pages}",
48
+ dataTableSortAsc: "Sort ascending",
49
+ dataTableSortDesc: "Sort descending",
50
+ dataTableHideColumn: "Hide column",
51
+ chartExportSvg: "Download SVG",
52
+ chartExportPng: "Download PNG",
53
+ chartNoData: "No data",
54
+ stepperStep: "Step {n}",
55
+ stepperCompleted: "Completed",
56
+ stepperCurrent: "Current step",
57
+ stepperError: "Needs attention",
58
+ statIncrease: "Increase",
59
+ statDecrease: "Decrease",
60
+ statNoChange: "No change",
61
+ notificationsForYou: "For you",
62
+ notificationsGeneral: "General",
63
+ notificationsHistory: "History",
64
+ datePresetToday: "Today",
65
+ datePresetYesterday: "Yesterday",
66
+ datePresetLastDays: "Last {n} days",
67
+ dateApply: "Apply",
68
+ dateClear: "Clear",
69
+ dateMaxSpan: "Up to {n} days",
70
+ filterAll: "All",
71
+ filterClear: "Clear filters",
72
+ statNoData: "No data",
73
+ heatmapLow: "Low",
74
+ heatmapHigh: "High",
75
+ dataTableFilter: "Filter",
76
+ dataTableLoading: "Loading data",
77
+ dropzoneTooMany: "{name}: up to {n} files",
78
+ calendarPrevious: "Previous month",
79
+ calendarNext: "Next month",
80
+ notificationUnread: "Unread",
81
+ statusMeaning: "What it means",
82
+ statusCause: "Why",
83
+ statusAction: "What to do"
30
84
  };
31
85
  const es = {
32
86
  close: "Cerrar",
@@ -54,7 +108,61 @@ const es = {
54
108
  questionnairePrevious: "Anterior",
55
109
  questionnaireSkip: "Omitir",
56
110
  questionnaireNext: "Siguiente",
57
- questionnaireSubmit: "Enviar"
111
+ questionnaireSubmit: "Enviar",
112
+ codeCopy: "Copiar c\xF3digo",
113
+ codeCopied: "Copiado",
114
+ notifications: "Notificaciones",
115
+ notificationsMarkAllRead: "Marcar todo como le\xEDdo",
116
+ notificationsEmpty: "Est\xE1s al d\xEDa",
117
+ notificationsUnread: "{n} sin leer",
118
+ datePickerPlaceholder: "Elige una fecha",
119
+ dateRangePlaceholder: "Elige un rango de fechas",
120
+ dropzoneTitle: "Suelta aqu\xED los ficheros",
121
+ dropzoneHint: "o haz clic para buscarlos",
122
+ dropzoneTooLarge: "{name} supera {max}",
123
+ dropzoneWrongType: "{name} no es un tipo de fichero admitido",
124
+ dataTableSearch: "Buscar\u2026",
125
+ dataTableColumns: "Columnas",
126
+ dataTableNoResults: "Sin resultados",
127
+ dataTableSelected: "{n} de {total} seleccionadas",
128
+ dataTableRowsPerPage: "Filas por p\xE1gina",
129
+ dataTablePage: "P\xE1gina {page} de {pages}",
130
+ dataTableSortAsc: "Orden ascendente",
131
+ dataTableSortDesc: "Orden descendente",
132
+ dataTableHideColumn: "Ocultar columna",
133
+ chartExportSvg: "Descargar SVG",
134
+ chartExportPng: "Descargar PNG",
135
+ chartNoData: "Sin datos",
136
+ stepperStep: "Paso {n}",
137
+ stepperCompleted: "Completado",
138
+ stepperCurrent: "Paso actual",
139
+ stepperError: "Requiere atenci\xF3n",
140
+ statIncrease: "Subida",
141
+ statDecrease: "Bajada",
142
+ statNoChange: "Sin cambios",
143
+ notificationsForYou: "Para ti",
144
+ notificationsGeneral: "General",
145
+ notificationsHistory: "Hist\xF3rico",
146
+ datePresetToday: "Hoy",
147
+ datePresetYesterday: "Ayer",
148
+ datePresetLastDays: "\xDAltimos {n} d\xEDas",
149
+ dateApply: "Aplicar",
150
+ dateClear: "Borrar",
151
+ dateMaxSpan: "Hasta {n} d\xEDas",
152
+ filterAll: "Todos",
153
+ filterClear: "Quitar filtros",
154
+ statNoData: "Sin dato",
155
+ heatmapLow: "Bajo",
156
+ heatmapHigh: "Alto",
157
+ dataTableFilter: "Filtrar",
158
+ dataTableLoading: "Cargando datos",
159
+ dropzoneTooMany: "{name}: m\xE1ximo {n} ficheros",
160
+ calendarPrevious: "Mes anterior",
161
+ calendarNext: "Mes siguiente",
162
+ notificationUnread: "Sin leer",
163
+ statusMeaning: "Qu\xE9 significa",
164
+ statusCause: "Por qu\xE9",
165
+ statusAction: "Qu\xE9 hacer"
58
166
  };
59
167
  const ptBR = {
60
168
  close: "Fechar",
@@ -82,7 +190,61 @@ const ptBR = {
82
190
  questionnairePrevious: "Anterior",
83
191
  questionnaireSkip: "Pular",
84
192
  questionnaireNext: "Pr\xF3xima",
85
- questionnaireSubmit: "Enviar"
193
+ questionnaireSubmit: "Enviar",
194
+ codeCopy: "Copiar c\xF3digo",
195
+ codeCopied: "Copiado",
196
+ notifications: "Notifica\xE7\xF5es",
197
+ notificationsMarkAllRead: "Marcar tudo como lido",
198
+ notificationsEmpty: "Voc\xEA est\xE1 em dia",
199
+ notificationsUnread: "{n} n\xE3o lidas",
200
+ datePickerPlaceholder: "Escolha uma data",
201
+ dateRangePlaceholder: "Escolha um intervalo de datas",
202
+ dropzoneTitle: "Solte os arquivos aqui",
203
+ dropzoneHint: "ou clique para procurar",
204
+ dropzoneTooLarge: "{name} excede {max}",
205
+ dropzoneWrongType: "{name} n\xE3o \xE9 um tipo de arquivo aceito",
206
+ dataTableSearch: "Pesquisar\u2026",
207
+ dataTableColumns: "Colunas",
208
+ dataTableNoResults: "Nenhum resultado",
209
+ dataTableSelected: "{n} de {total} selecionadas",
210
+ dataTableRowsPerPage: "Linhas por p\xE1gina",
211
+ dataTablePage: "P\xE1gina {page} de {pages}",
212
+ dataTableSortAsc: "Ordem crescente",
213
+ dataTableSortDesc: "Ordem decrescente",
214
+ dataTableHideColumn: "Ocultar coluna",
215
+ chartExportSvg: "Baixar SVG",
216
+ chartExportPng: "Baixar PNG",
217
+ chartNoData: "Sem dados",
218
+ stepperStep: "Etapa {n}",
219
+ stepperCompleted: "Conclu\xEDdo",
220
+ stepperCurrent: "Etapa atual",
221
+ stepperError: "Requer aten\xE7\xE3o",
222
+ statIncrease: "Aumento",
223
+ statDecrease: "Queda",
224
+ statNoChange: "Sem altera\xE7\xE3o",
225
+ notificationsForYou: "Para voc\xEA",
226
+ notificationsGeneral: "Geral",
227
+ notificationsHistory: "Hist\xF3rico",
228
+ datePresetToday: "Hoje",
229
+ datePresetYesterday: "Ontem",
230
+ datePresetLastDays: "\xDAltimos {n} dias",
231
+ dateApply: "Aplicar",
232
+ dateClear: "Limpar",
233
+ dateMaxSpan: "At\xE9 {n} dias",
234
+ filterAll: "Todos",
235
+ filterClear: "Limpar filtros",
236
+ statNoData: "Sem dado",
237
+ heatmapLow: "Baixo",
238
+ heatmapHigh: "Alto",
239
+ dataTableFilter: "Filtrar",
240
+ dataTableLoading: "Carregando dados",
241
+ dropzoneTooMany: "{name}: m\xE1ximo de {n} arquivos",
242
+ calendarPrevious: "M\xEAs anterior",
243
+ calendarNext: "Pr\xF3ximo m\xEAs",
244
+ notificationUnread: "N\xE3o lida",
245
+ statusMeaning: "O que significa",
246
+ statusCause: "Por qu\xEA",
247
+ statusAction: "O que fazer"
86
248
  };
87
249
  const dsCatalogs = { en, es, "pt-BR": ptBR };
88
250
  function resolveDsLocale(tag) {
@@ -90,6 +252,9 @@ function resolveDsLocale(tag) {
90
252
  const base = tag.split("-")[0];
91
253
  return DS_LOCALES.find((l) => l === tag) ?? DS_LOCALES.find((l) => l.split("-")[0] === base) ?? DS_DEFAULT_LOCALE;
92
254
  }
255
+ function dsFormat(text, vars) {
256
+ return text.replace(/\{(\w+)\}/g, (m, k) => k in vars ? String(vars[k]) : m);
257
+ }
93
258
  function dsMessagesFor(tag, overrides) {
94
259
  return { ...dsCatalogs[resolveDsLocale(tag)], ...overrides };
95
260
  }
@@ -104,6 +269,7 @@ export {
104
269
  DS_RTL_LANGS,
105
270
  dsCatalogs,
106
271
  dsDirection,
272
+ dsFormat,
107
273
  dsMessagesFor,
108
274
  resolveDsLocale
109
275
  };
package/dist/styles.css CHANGED
@@ -102,6 +102,7 @@
102
102
  --radius-avatar: var(--ds-radius-avatar);
103
103
  --radius-bubble: var(--ds-radius-bubble);
104
104
  --radius-xs: var(--ds-radius-xs);
105
+ --radius-code: var(--ds-radius-code);
105
106
  --radius-tooltip: var(--ds-radius-tooltip);
106
107
  --radius-tab: var(--ds-radius-tab);
107
108
  --radius-field-multiline: var(--ds-radius-field-multiline);
@@ -128,6 +129,7 @@
128
129
  --ds-radius-chip: var(--ds-radius-xl); /* adjuntos y fichas */
129
130
  --ds-radius-avatar: var(--ds-radius-pill);
130
131
  --ds-radius-bubble: var(--ds-radius-overlay);
132
+ --ds-radius-code: var(--ds-radius-lg); /* bloque de código */
131
133
  --ds-radius-xs: 2px; /* marcas de leyenda y flecha del tooltip */
132
134
  --ds-radius-tooltip: var(--ds-radius-2xl);
133
135
  --ds-radius-tab: var(--ds-radius-xl);
@@ -296,6 +298,9 @@
296
298
  --ds-field-bg-hover: color-mix(in oklch, var(--input) 50%, transparent);
297
299
  --ds-invalid-border: var(--destructive); /* borde de un campo con error */
298
300
  --ds-switch-track-off: var(--input); /* carril del interruptor apagado */
301
+ --ds-code-bg: var(--inset); /* fondo del código */
302
+ --ds-code-fg: var(--inset-foreground);
303
+ --ds-code-muted: var(--muted-foreground); /* números de línea y cabecera */
299
304
  --ds-check-bg: transparent; /* fondo de casilla y radio sin marcar */
300
305
  --ds-row-hover: color-mix(in oklch, var(--muted) 50%, transparent); /* fila señalada (tabla, acordeón abierto, item muted) */
301
306
  --ds-choice-selected: color-mix(in oklch, var(--primary) 10%, transparent); /* opción elegida en tarjeta */
@@ -328,6 +333,8 @@
328
333
  --ds-tab-line-w: 2px;
329
334
  --ds-tab-line-offset: -5px;
330
335
  --ds-table-head-h: 3rem;
336
+ --ds-table-head-h-compact: calc(var(--ds-table-head-h) * 0.75); /* tabla densa */
337
+ --ds-cell-p-compact: calc(var(--ds-cell-p) * 0.5);
331
338
  --ds-popover-w: 18rem;
332
339
  --ds-hover-card-w: 18rem;
333
340
  --ds-sheet-w: 24rem;
@@ -399,7 +406,35 @@
399
406
  --ds-button-px-md: 1rem;
400
407
  --ds-button-px-lg: 1rem;
401
408
  --ds-badge-px: 0.625rem;
402
- --ds-banner-px: 1rem; /* aviso de página (Banner) */
409
+ --ds-panel-p: var(--ds-card-spacing); /* Panel: superficie con relleno uniforme */
410
+ --ds-panel-p-sm: var(--ds-card-spacing-sm);
411
+ --ds-panel-p-lg: 2rem;
412
+ --ds-code-p: 1rem; /* bloque de código */
413
+ --ds-code-inline-px: 0.375rem; /* código en línea */
414
+ --ds-code-inline-size: 0.875em;
415
+ /* Piezas de datos y estructura (0.10.0) */
416
+ --ds-page-max-w: 72rem; /* ancho máximo del contenido de una vista (PageHeader) */
417
+ --ds-page-gap: 1.5rem;
418
+ --ds-section-gap: 1rem;
419
+ --ds-stat-value-weight: 600; /* cifra de un KPI */
420
+ --ds-stat-accent-w: calc(var(--ds-rule-w) * 3); /* filete de tono del KPI */
421
+ --ds-sparkline-h: 2rem;
422
+ --ds-sparkline-w: 1.5px; /* grosor del trazo */
423
+ --ds-status-dot: 0.5rem;
424
+ --ds-motion-pulse: calc(var(--ds-motion-blink) * 2); /* latido de un estado vivo */
425
+ --ds-proportion-h: 0.5rem; /* barra de proporción */
426
+ --ds-legend-swatch: 0.625rem;
427
+ --ds-heatmap-cell: 2rem;
428
+ --ds-heatmap-low: color-mix(in oklch, var(--ds-heatmap-high) 6%, var(--card)); /* mapa de calor: extremo bajo (distinto de la tarjeta) */
429
+ --ds-hatch: repeating-linear-gradient(-45deg, color-mix(in oklch, var(--muted-foreground) 25%, transparent) 0 2px, transparent 2px 6px); /* rayado de «sin dato» */
430
+ --ds-heatmap-high: var(--chart-1); /* mapa de calor: extremo alto */
431
+ --ds-timeline-dot: 0.625rem;
432
+ --ds-step-size: 2rem; /* indicador de un paso */
433
+ --ds-notifications-w: 24rem;
434
+ --ds-notifications-max-h: 24rem; /* alto máximo de la lista antes de desplazarse */
435
+ --ds-dropzone-p: 2rem;
436
+ --ds-filter-gap: 0.5rem;
437
+ --ds-banner-px: 1rem; /* aviso de página (Banner) */
403
438
  --ds-banner-py: 0.625rem;
404
439
  --ds-tabs-gap: 0.25rem; /* separación entre pestañas cuando el tema las separa */
405
440
 
@@ -684,13 +719,15 @@
684
719
  }
685
720
 
686
721
  /*
687
- * TARJETA: radio `xl`, borde de 1px y sombra de reposo. `ui/card.tsx` ya lleva
722
+ * TARJETA y PANEL: radio de tarjeta, filete (`--ds-rule-w`) y sombra de reposo. `ui/card.tsx` ya lleva
688
723
  * estos valores; esta regla los GARANTIZA aunque se regenere con la CLI de
689
724
  * shadcn. Material de la tarjeta: `--ds-card-backdrop`.
690
725
  */
691
- [data-slot='card'] {
692
- @apply rounded-xl shadow-card ring-0;
693
- border: 1px solid var(--border);
726
+ [data-slot='card'],
727
+ [data-slot='panel'][data-variant='default'],
728
+ [data-slot='stat'][data-variant='card'] {
729
+ @apply rounded-card shadow-card ring-0;
730
+ border: var(--ds-rule-w) solid var(--border);
694
731
  -webkit-backdrop-filter: var(--ds-card-backdrop);
695
732
  backdrop-filter: var(--ds-card-backdrop);
696
733
  }
@@ -851,6 +888,7 @@
851
888
  */
852
889
  @media (prefers-reduced-transparency: reduce) {
853
890
  [data-slot='card'],
891
+ [data-slot='panel'],
854
892
  [data-slot='popover-content'],
855
893
  [data-slot='dropdown-menu-content'],
856
894
  [data-slot='dropdown-menu-sub-content'],
@@ -302,7 +302,9 @@
302
302
  }
303
303
 
304
304
  /* Tarjetas: blancas, sin borde, solo la sombra teñida */
305
- [data-slot='card'] {
305
+ [data-slot='card'],
306
+ [data-slot='panel'][data-variant='default'],
307
+ [data-slot='stat'][data-variant='card'] {
306
308
  border-color: transparent;
307
309
  }
308
310
 
@@ -302,7 +302,9 @@
302
302
  }
303
303
 
304
304
  /* Tarjetas: blancas, sin borde, solo la sombra teñida */
305
- [data-slot='card'] {
305
+ [data-slot='card'],
306
+ [data-slot='panel'][data-variant='default'],
307
+ [data-slot='stat'][data-variant='card'] {
306
308
  border-color: transparent;
307
309
  }
308
310
 
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "friendly",
3
+ "light": {
4
+ "palette": [
5
+ "#5f6ec9",
6
+ "#fbb232",
7
+ "#1db87a",
8
+ "#e5484d",
9
+ "#3784f7",
10
+ "#2962c0",
11
+ "#097650",
12
+ "#955800",
13
+ "#bb3137"
14
+ ],
15
+ "foreground": "#232450",
16
+ "muted": "#6b6d96",
17
+ "border": "rgba(35, 36, 80, 0.08)",
18
+ "surface": "#ffffff",
19
+ "surfaceForeground": "#232450",
20
+ "fontSans": "'Rubik', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
21
+ "fontDisplay": "'Rubik', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
22
+ "motionBaseMs": 200,
23
+ "motionSlowMs": 300
24
+ },
25
+ "dark": {
26
+ "palette": [
27
+ "#8a98f0",
28
+ "#fbb232",
29
+ "#3fd397",
30
+ "#ef5d62",
31
+ "#569cff",
32
+ "#8dbbff",
33
+ "#ff7a7f"
34
+ ],
35
+ "foreground": "#ecedfa",
36
+ "muted": "#a3a6d4",
37
+ "border": "rgba(255, 255, 255, 0.09)",
38
+ "surface": "#25275c",
39
+ "surfaceForeground": "#ecedfa",
40
+ "fontSans": "'Rubik', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
41
+ "fontDisplay": "'Rubik', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
42
+ "motionBaseMs": 200,
43
+ "motionSlowMs": 300
44
+ }
45
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "qratia",
3
+ "light": {
4
+ "palette": [
5
+ "#2a78d6",
6
+ "#eb6834",
7
+ "#1baf7a",
8
+ "#eda100",
9
+ "#e87ba4",
10
+ "#006a91",
11
+ "#05773b",
12
+ "#975800",
13
+ "#bb0916",
14
+ "#00b4d8"
15
+ ],
16
+ "foreground": "#0a1128",
17
+ "muted": "#5b6b84",
18
+ "border": "#dce6f0",
19
+ "surface": "#f5fafe",
20
+ "surfaceForeground": "#0a1128",
21
+ "fontSans": "'Instrument Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
22
+ "fontDisplay": "'Instrument Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
23
+ "motionBaseMs": 200,
24
+ "motionSlowMs": 300
25
+ },
26
+ "dark": {
27
+ "palette": [
28
+ "#3987e5",
29
+ "#d95926",
30
+ "#199e70",
31
+ "#c98500",
32
+ "#d55181",
33
+ "#73d3f1",
34
+ "#55c483",
35
+ "#e8aa4e",
36
+ "#f66d62",
37
+ "#00e5ff"
38
+ ],
39
+ "foreground": "#e9f0f8",
40
+ "muted": "#93a3bc",
41
+ "border": "#28324a",
42
+ "surface": "#19233e",
43
+ "surfaceForeground": "#e9f0f8",
44
+ "fontSans": "'Instrument Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
45
+ "fontDisplay": "'Instrument Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
46
+ "motionBaseMs": 200,
47
+ "motionSlowMs": 300
48
+ }
49
+ }
@@ -339,7 +339,9 @@
339
339
  }
340
340
 
341
341
  /* ── SUPERFICIES: filete suave y una arista inferior más marcada ── */
342
- [data-slot='card'] {
342
+ [data-slot='card'],
343
+ [data-slot='panel']:is([data-variant='default'], [data-variant='outline']),
344
+ [data-slot='stat'][data-variant='card'] {
343
345
  border: var(--ds-rule-w) solid var(--border);
344
346
  border-bottom: var(--ds-key-edge-w) solid var(--ds-key-edge);
345
347
  box-shadow: none;
@@ -339,7 +339,9 @@
339
339
  }
340
340
 
341
341
  /* ── SUPERFICIES: filete suave y una arista inferior más marcada ── */
342
- [data-slot='card'] {
342
+ [data-slot='card'],
343
+ [data-slot='panel']:is([data-variant='default'], [data-variant='outline']),
344
+ [data-slot='stat'][data-variant='card'] {
343
345
  border: var(--ds-rule-w) solid var(--border);
344
346
  border-bottom: var(--ds-key-edge-w) solid var(--ds-key-edge);
345
347
  box-shadow: none;