@dashadmin/dash-components 1.3.72 → 1.3.74-srcfree.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 (60) hide show
  1. package/package.json +24 -21
  2. package/src/components/AuditLog/AuditLog.tsx +0 -490
  3. package/src/components/AuditLog/index.ts +0 -2
  4. package/src/components/AutoCompleteArrayInput/AutoCompleteCheckBoxInput.tsx +0 -917
  5. package/src/components/AutoCompleteArrayInput/AutocompleteCheckBoxArrayInput.tsx +0 -39
  6. package/src/components/AutoCompleteArrayInputAutoSearch/AutoCompleteCheckBoxInput.tsx +0 -916
  7. package/src/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayAutoSearch.tsx.wip +0 -42
  8. package/src/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayInput.tsx +0 -44
  9. package/src/components/Json/Json.tsx +0 -312
  10. package/src/components/JsonColorSelector/JsonColorSelector.tsx +0 -1443
  11. package/src/components/JsonColorSelector/JsonColorSelector.tsx.bkup +0 -746
  12. package/src/components/JsonColorSelector/JsonColorSelectorEnhanced.tsx +0 -1135
  13. package/src/components/JsonColorSelector/JsonCssVarValues.tsx +0 -867
  14. package/src/components/JsonColorSelector/components/BasicColorSelector.tsx +0 -333
  15. package/src/components/JsonColorSelector/components/ColorEditDialog.tsx +0 -495
  16. package/src/components/JsonColorSelector/components/ColorPaletteItem.tsx +0 -80
  17. package/src/components/JsonColorSelector/components/ImageColorExtractor.tsx +0 -420
  18. package/src/components/JsonColorSelector/helpers/functions.tsx +0 -123
  19. package/src/components/JsonColorSelector/helpers/paletteDerivation.ts +0 -367
  20. package/src/components/JsonColorSelector/interfaces/interfaces.tsx +0 -22
  21. package/src/components/JsonColorSelector/useAsyncColorThief.tsx +0 -97
  22. package/src/components/ListActive/ListActive.tsx +0 -106
  23. package/src/components/ListActive/ListBoolean.tsx +0 -96
  24. package/src/components/NotificationPreferences/NotificationPreferences.tsx +0 -480
  25. package/src/components/NotificationPreferences/index.tsx +0 -2
  26. package/src/components/SearchableSelects/RASearchableSelect.tsx +0 -303
  27. package/src/components/SearchableSelects/RASearchableSelectCheckboxes.tsx +0 -617
  28. package/src/components/SearchableSelects/RASearchableSelectChips.tsx +0 -561
  29. package/src/components/SearchableSelects/RASearchableSelectChipsRecordContext.tsx +0 -366
  30. package/src/components/SearchableSelects/SearchableSelect.tsx +0 -323
  31. package/src/components/SearchableSelects/SearchableSelectCheckboxes.tsx +0 -358
  32. package/src/components/SortableDataGrid/README.md +0 -1
  33. package/src/components/SortableDataGrid/SortableDataGrid.tsx +0 -56
  34. package/src/components/SortableDataGrid/SortableDataGridBody.tsx +0 -175
  35. package/src/components/SortableDataGrid/SortableDataGridHeader.tsx +0 -171
  36. package/src/components/SortableDataGrid/SortableDataGridRow.tsx +0 -247
  37. package/src/components/Upload/SingleImageUploader.tsx +0 -55
  38. package/src/components/custom/PackageCopyMethod.tsx +0 -109
  39. package/src/components/custom/PackageRadioButtonGroup.tsx +0 -49
  40. package/src/components/dialog/Basic.tsx +0 -11
  41. package/src/components/dialog/Correct.tsx +0 -16
  42. package/src/components/dialog/Error.tsx +0 -15
  43. package/src/components/dialog/Info.tsx +0 -15
  44. package/src/components/dialog/InfoV2.tsx +0 -35
  45. package/src/components/dialog/NotFound.tsx +0 -18
  46. package/src/components/dialog/QuickSearch.tsx +0 -115
  47. package/src/components/notifications/NotificationsCenter.tsx +0 -743
  48. package/src/components/notifications/index.ts +0 -42
  49. package/src/components/tables/PaginationComponent.tsx +0 -17
  50. package/src/components/theme/AppLoadingFallback.tsx +0 -42
  51. package/src/components/theme/ErrorBoundary.tsx +0 -57
  52. package/src/components/theme/InitialLoader.tsx +0 -16
  53. package/src/components/theme/NotFound.tsx +0 -124
  54. package/src/components/theme/NotResults.tsx +0 -56
  55. package/src/hooks/useDraggable.ts +0 -11
  56. package/src/hooks/useNotifications.ts +0 -14
  57. package/src/hooks/useQuickSearch.tsx +0 -29
  58. package/src/index.tsx +0 -77
  59. package/src/styles/index.less +0 -0
  60. package/src/utils/setNativeValue.tsx +0 -23
@@ -1,367 +0,0 @@
1
- /**
2
- * Palette derivation — computes the full DASH theme palette from 5 base colors
3
- * per mode, entirely in the frontend (no AI required).
4
- *
5
- * Design-system bases (per mode, from the DASH Design System):
6
- * --primary-color brand color (sidebar, table headers, links)
7
- * --primary-contrast companion shade of primary (darker variant, NOT text color)
8
- * --secondary-color action/CTA color (buttons)
9
- * --secondary-contrast text color on secondary (buttons text)
10
- * --highlight-color accent color (badges, highlights)
11
- *
12
- * Derivation rules were reverse-engineered from config/tenants.php theme_colors
13
- * defaults and the kitchntabs app dash-variables.less overrides:
14
- * - Brand families (sidebar, buttons, links, table headers, scrollbars) inherit
15
- * from the 5 bases via lighten/darken/alpha transforms.
16
- * - Greyscale neutrals (module-bg, component-bg, framed_layout-bg, text-*, ...)
17
- * and semantic alerts (alert-*) are intentionally NOT derived — they keep
18
- * their current/template values so backgrounds stay greyscale and alert
19
- * semantics (red=error, green=success...) are never lost.
20
- */
21
-
22
- export type ThemeMode = 'light' | 'dark';
23
-
24
- export interface BasicPalette {
25
- primaryColor: string;
26
- primaryContrast: string;
27
- secondaryColor: string;
28
- secondaryContrast: string;
29
- highlightColor: string;
30
- // Page/surface background pair — NOT derived from the 5 brand bases above (they
31
- // stay neutral so content stays readable); set and extracted as plain pass-through
32
- // values. Real usage today: MUI DataGrid row striping (bodybg-primary = even rows,
33
- // bodybg-secondary = odd rows) — see dash-styles/src/index.tsx.
34
- bodyBgPrimary: string;
35
- bodyBgSecondary: string;
36
- }
37
-
38
- export const BASIC_COLOR_DEFS: { key: keyof BasicPalette; cssBase: string; label: string; description: string }[] = [
39
- { key: 'primaryColor', cssBase: 'primary-color', label: 'Primary', description: 'Brand color: sidebar, headers, links' },
40
- { key: 'primaryContrast', cssBase: 'primary-contrast', label: 'Primary Contrast', description: 'Darker companion of primary' },
41
- { key: 'secondaryColor', cssBase: 'secondary-color', label: 'Secondary', description: 'Action color: buttons, CTAs' },
42
- { key: 'secondaryContrast', cssBase: 'secondary-contrast', label: 'Secondary Contrast', description: 'Text over secondary' },
43
- { key: 'highlightColor', cssBase: 'highlight-color', label: 'Highlight', description: 'Accent: badges, highlights' },
44
- { key: 'bodyBgPrimary', cssBase: 'bodybg-primary', label: 'Body Background', description: 'Page surface (e.g. table row background)' },
45
- { key: 'bodyBgSecondary', cssBase: 'bodybg-secondary', label: 'Body Background 2', description: 'Page surface, alternate (e.g. striped rows)' },
46
- ];
47
-
48
- // ---------------------------------------------------------------------------
49
- // Color math
50
- // ---------------------------------------------------------------------------
51
-
52
- interface RGBA { r: number; g: number; b: number; a: number }
53
-
54
- const clamp = (v: number, min = 0, max = 255) => Math.min(max, Math.max(min, v));
55
-
56
- export const parseColor = (input: string): RGBA | null => {
57
- if (!input) return null;
58
- const value = input.trim();
59
-
60
- if (value.startsWith('#')) {
61
- let hex = value.slice(1);
62
- if (hex.length === 3) hex = hex.split('').map(c => c + c).join('');
63
- if (hex.length === 6 || hex.length === 8) {
64
- const r = parseInt(hex.slice(0, 2), 16);
65
- const g = parseInt(hex.slice(2, 4), 16);
66
- const b = parseInt(hex.slice(4, 6), 16);
67
- const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1;
68
- if ([r, g, b].some(isNaN)) return null;
69
- return { r, g, b, a };
70
- }
71
- return null;
72
- }
73
-
74
- const rgbMatch = value.match(/rgba?\(([^)]+)\)/i);
75
- if (rgbMatch) {
76
- const parts = rgbMatch[1].split(',').map(p => parseFloat(p.trim()));
77
- if (parts.length >= 3 && parts.slice(0, 3).every(n => !isNaN(n))) {
78
- return { r: clamp(parts[0]), g: clamp(parts[1]), b: clamp(parts[2]), a: parts[3] !== undefined && !isNaN(parts[3]) ? parts[3] : 1 };
79
- }
80
- }
81
- return null;
82
- };
83
-
84
- export const toHex = ({ r, g, b }: RGBA): string =>
85
- `#${[r, g, b].map(v => Math.round(clamp(v)).toString(16).padStart(2, '0')).join('')}`;
86
-
87
- /** Mix `color` toward `target` by weight 0..1 (0 = color, 1 = target). */
88
- const mixRgb = (color: RGBA, target: RGBA, weight: number): RGBA => ({
89
- r: color.r + (target.r - color.r) * weight,
90
- g: color.g + (target.g - color.g) * weight,
91
- b: color.b + (target.b - color.b) * weight,
92
- a: color.a,
93
- });
94
-
95
- const WHITE: RGBA = { r: 255, g: 255, b: 255, a: 1 };
96
- const BLACK: RGBA = { r: 0, g: 0, b: 0, a: 1 };
97
-
98
- /** Lighten a color by mixing toward white. amount 0..1 */
99
- export const lighten = (color: string, amount: number): string => {
100
- const rgba = parseColor(color);
101
- if (!rgba) return color;
102
- return toHex(mixRgb(rgba, WHITE, amount));
103
- };
104
-
105
- /** Darken a color by mixing toward black. amount 0..1 */
106
- export const darken = (color: string, amount: number): string => {
107
- const rgba = parseColor(color);
108
- if (!rgba) return color;
109
- return toHex(mixRgb(rgba, BLACK, amount));
110
- };
111
-
112
- /** rgba() string of a color with the given alpha. */
113
- export const withAlpha = (color: string, alphaValue: number): string => {
114
- const rgba = parseColor(color);
115
- if (!rgba) return color;
116
- return `rgba(${Math.round(rgba.r)}, ${Math.round(rgba.g)}, ${Math.round(rgba.b)}, ${alphaValue})`;
117
- };
118
-
119
- export const relativeLuminance = (color: string): number => {
120
- const rgba = parseColor(color);
121
- if (!rgba) return 0;
122
- return (0.299 * rgba.r + 0.587 * rgba.g + 0.114 * rgba.b) / 255;
123
- };
124
-
125
- /** '#ffffff' or '#000000' depending on which reads better over the color. */
126
- export const contrastText = (color: string): string =>
127
- relativeLuminance(color) > 0.55 ? '#000000' : '#ffffff';
128
-
129
- // ---------------------------------------------------------------------------
130
- // HSL helpers (for image → bases mapping)
131
- // ---------------------------------------------------------------------------
132
-
133
- const rgbToHsl = ({ r, g, b }: RGBA): { h: number; s: number; l: number } => {
134
- const rn = r / 255, gn = g / 255, bn = b / 255;
135
- const max = Math.max(rn, gn, bn), min = Math.min(rn, gn, bn);
136
- const l = (max + min) / 2;
137
- if (max === min) return { h: 0, s: 0, l };
138
- const d = max - min;
139
- const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
140
- let h: number;
141
- if (max === rn) h = ((gn - bn) / d + (gn < bn ? 6 : 0)) * 60;
142
- else if (max === gn) h = ((bn - rn) / d + 2) * 60;
143
- else h = ((rn - gn) / d + 4) * 60;
144
- return { h, s, l };
145
- };
146
-
147
- const hueDistance = (a: number, b: number): number => {
148
- const d = Math.abs(a - b) % 360;
149
- return d > 180 ? 360 - d : d;
150
- };
151
-
152
- // ---------------------------------------------------------------------------
153
- // Brand-derived palette
154
- // ---------------------------------------------------------------------------
155
-
156
- /**
157
- * Compute the brand-derived subset of the theme for one mode.
158
- * Returns keys WITHOUT the mode suffix. Neutral/semantic keys are deliberately
159
- * absent — callers must merge this over the existing full palette.
160
- */
161
- export const deriveModePalette = (bases: BasicPalette, mode: ThemeMode): Record<string, string> => {
162
- const P = bases.primaryColor;
163
- const PC = bases.primaryContrast;
164
- const S = bases.secondaryColor;
165
- const SC = bases.secondaryContrast;
166
- const H = bases.highlightColor;
167
- const dark = mode === 'dark';
168
-
169
- return {
170
- // Core bases
171
- 'primary-color': P,
172
- 'primary-contrast': PC,
173
- 'primary-contrast-color': PC,
174
- 'secondary-color': S,
175
- 'secondary-contrast': SC,
176
- 'highlight-color': H,
177
- 'highlight-color-contrast': contrastText(H),
178
-
179
- // Page background pair — pass-through, not derived from the brand bases.
180
- 'bodybg-primary': bases.bodyBgPrimary,
181
- 'bodybg-secondary': bases.bodyBgSecondary,
182
-
183
- // Buttons — action family from secondary
184
- 'btn-bg': S,
185
- 'btn-primary-bg': S,
186
- 'btn-hover-bg': darken(S, 0.14),
187
- 'btn-active-bg': darken(S, 0.24),
188
- 'btn-border-color': darken(S, 0.10),
189
- 'btn-color': SC,
190
- 'btn-primary-color': SC,
191
-
192
- // Links — primary family
193
- 'link-color': dark ? lighten(P, 0.30) : darken(P, 0.12),
194
- 'link-hover': dark ? lighten(P, 0.45) : lighten(P, 0.18),
195
- 'link-hover-color': dark ? lighten(P, 0.45) : lighten(P, 0.18),
196
- 'link-active': dark ? lighten(P, 0.20) : darken(P, 0.24),
197
- 'link-active-color': dark ? lighten(P, 0.20) : darken(P, 0.24),
198
- 'dash-link-color': dark ? lighten(P, 0.35) : darken(P, 0.16),
199
-
200
- // Table headers — primary family
201
- 'table-header-bg': dark ? darken(P, 0.24) : P,
202
- 'table-header-color': contrastText(dark ? darken(P, 0.24) : P),
203
-
204
- // Header badge — highlight family
205
- 'header-badge': H,
206
- 'header-badge-hover': lighten(H, 0.12),
207
-
208
- // Dash sidebar — primary family
209
- 'dash-sidebar-bg': dark ? darken(P, 0.30) : P,
210
- 'dash-sidebar-bg-primary': dark ? darken(P, 0.30) : P,
211
- 'dash-sidebar-bg-contrast': dark ? lighten(P, 0.08) : PC,
212
- 'dash-sidebar-bg-hover': dark ? lighten(P, 0.08) : PC,
213
- 'dash-sidebar-submenu-bg-contrast': dark ? lighten(P, 0.08) : PC,
214
- 'dash-sidebar-submenu-bg-primary': dark ? 'rgba(18, 18, 18, 0.16)' : lighten(P, 0.85),
215
- 'dash-sidebar-color': dark ? lighten(P, 0.25) : contrastText(P),
216
- 'dash-sidebar-color-primary': dark ? lighten(P, 0.25) : contrastText(P),
217
- 'dash-sidebar-color-active': dark ? '#fafafa' : lighten(P, 0.85),
218
- 'dash-sidebar-color-contrast': dark ? lighten(P, 0.55) : lighten(P, 0.85),
219
- 'dash-sidebar-submenu-color-contrast': dark ? lighten(P, 0.55) : lighten(P, 0.85),
220
- 'dash-sidebar-submenu-color-primary': dark ? '#d4d4d4' : P,
221
- 'dash-sidebar-icon-color': dark ? '#f5f5f5' : P,
222
- 'dash-sidebar-icon-color-primary': dark ? '#f5f5f5' : P,
223
- 'dash-sidebar-icon-color-active': dark ? P : lighten(P, 0.85),
224
- 'dash-sidebar-icon-color-secondary': dark ? lighten(P, 0.10) : lighten(P, 0.85),
225
- 'dash-sidebar-handle-primary': dark ? withAlpha(lighten(P, 0.15), 0.4) : 'rgba(255, 255, 255, 0.2)',
226
- 'dash-sidebar-handle-contrast': dark ? withAlpha(P, 0.6) : 'rgba(255, 255, 255, 0.5)',
227
-
228
- // Dash surfaces / scrollbars — primary family
229
- 'dash-scroll-thumb-color': dark ? P : lighten(P, 0.30),
230
- 'dash-scroll-track-color': dark ? darken(P, 0.30) : lighten(P, 0.88),
231
- 'dash-main-background': dark ? darken(P, 0.35) : '#ffffff',
232
- 'dash-framed-layout-background': dark ? P : '#ffffff',
233
- 'dash-border-color': dark ? '#000000' : lighten(P, 0.72),
234
- 'body-background': dark ? darken(P, 0.28) : P,
235
- 'component-active-background': dark ? darken(P, 0.28) : '#e6e6e6',
236
- 'component-hover-background': dark ? darken(P, 0.22) : '#f8f8f8',
237
- 'component-border-color': dark ? '#000000' : lighten(P, 0.72),
238
- 'border-color-base': dark ? '#000000' : lighten(P, 0.72),
239
- 'border-color-split': dark ? '#000000' : lighten(P, 0.72),
240
- 'module-background': dark ? darken(P, 0.34) : '#f8f8f8',
241
- };
242
- };
243
-
244
- /** Full `{ 'key--mode': value }` record for the brand-derived keys, both modes. */
245
- export const deriveBrandPairs = (light: BasicPalette, darkBases: BasicPalette): Record<string, string> => {
246
- const out: Record<string, string> = {};
247
- Object.entries(deriveModePalette(light, 'light')).forEach(([k, v]) => { out[`${k}--light`] = v; });
248
- Object.entries(deriveModePalette(darkBases, 'dark')).forEach(([k, v]) => { out[`${k}--dark`] = v; });
249
- return out;
250
- };
251
-
252
- // ---------------------------------------------------------------------------
253
- // Reading bases from an existing palette
254
- // ---------------------------------------------------------------------------
255
-
256
- const FALLBACK_BASES: Record<ThemeMode, BasicPalette> = {
257
- light: {
258
- primaryColor: '#41ab5d',
259
- primaryContrast: '#005a32',
260
- secondaryColor: '#367800',
261
- secondaryContrast: '#ffffff',
262
- highlightColor: '#49a000',
263
- bodyBgPrimary: '#ffffff',
264
- bodyBgSecondary: '#ececec',
265
- },
266
- dark: {
267
- primaryColor: '#41ab5d',
268
- primaryContrast: '#005a32',
269
- secondaryColor: '#238b45',
270
- secondaryContrast: '#f7fcf5',
271
- highlightColor: '#74c476',
272
- bodyBgPrimary: '#101010',
273
- bodyBgSecondary: 'rgba(36, 36, 36, 1)',
274
- },
275
- };
276
-
277
- /** Extract the 7 base colors for a mode from a full palette record; falls back to defaults. */
278
- export const extractBases = (colors: Record<string, string>, mode: ThemeMode): BasicPalette => {
279
- const get = (base: string, fallback: string) => {
280
- const v = colors[`${base}--${mode}`];
281
- return v && parseColor(v) ? v : fallback;
282
- };
283
- const fb = FALLBACK_BASES[mode];
284
- return {
285
- primaryColor: get('primary-color', fb.primaryColor),
286
- primaryContrast: get('primary-contrast', fb.primaryContrast),
287
- secondaryColor: get('secondary-color', fb.secondaryColor),
288
- secondaryContrast: get('secondary-contrast', fb.secondaryContrast),
289
- highlightColor: get('highlight-color', fb.highlightColor),
290
- bodyBgPrimary: get('bodybg-primary', fb.bodyBgPrimary),
291
- bodyBgSecondary: get('bodybg-secondary', fb.bodyBgSecondary),
292
- };
293
- };
294
-
295
- // ---------------------------------------------------------------------------
296
- // Image palette → bases (local, no AI)
297
- // ---------------------------------------------------------------------------
298
-
299
- /**
300
- * Map a ColorThief palette (RGB triples ordered by dominance) to the 5 base
301
- * colors for both modes. Pure frontend heuristic:
302
- * primary = most dominant sufficiently-saturated color
303
- * secondary = next color with a distinct hue (>40° away)
304
- * highlight = most vivid remaining color
305
- * Contrasts are computed (primary-contrast = darker companion,
306
- * secondary-contrast = readable text color).
307
- */
308
- export const basesFromImagePalette = (palette: number[][]): { light: BasicPalette; dark: BasicPalette } => {
309
- const candidates = palette
310
- .map(rgb => {
311
- const rgba: RGBA = { r: rgb[0], g: rgb[1], b: rgb[2], a: 1 };
312
- return { hex: toHex(rgba), ...rgbToHsl(rgba) };
313
- });
314
-
315
- const saturated = candidates.filter(c => c.s > 0.15 && c.l > 0.08 && c.l < 0.92);
316
- const pool = saturated.length > 0 ? saturated : candidates;
317
-
318
- const primary = pool[0];
319
- const secondary =
320
- pool.find(c => c !== primary && hueDistance(c.h, primary.h) > 40) ||
321
- pool.find(c => c !== primary) ||
322
- primary;
323
- const vividness = (c: { s: number; l: number }) => c.s * (1 - Math.abs(c.l - 0.5) * 2);
324
- const highlight =
325
- [...pool]
326
- .filter(c => c !== primary && c !== secondary)
327
- .sort((a, b) => vividness(b) - vividness(a))[0] ||
328
- secondary;
329
-
330
- // Normalize for usable contrast: primary shouldn't be near-white/near-black.
331
- const normalize = (hex: string, minL = 0.18, maxL = 0.72): string => {
332
- const l = rgbToHsl(parseColor(hex)!).l;
333
- if (l > maxL) return darken(hex, (l - maxL) / (1 - maxL) * 0.6);
334
- if (l < minL) return lighten(hex, (minL - l) / minL * 0.6);
335
- return hex;
336
- };
337
-
338
- const pLight = normalize(primary.hex);
339
- const sLight = normalize(secondary.hex);
340
-
341
- const light: BasicPalette = {
342
- primaryColor: pLight,
343
- primaryContrast: darken(pLight, 0.40),
344
- secondaryColor: sLight,
345
- secondaryContrast: contrastText(sLight),
346
- highlightColor: normalize(highlight.hex, 0.25, 0.8),
347
- // Body background stays neutral even when deriving from an image — a page
348
- // background tinted to a vivid extracted color reads as garish/low-contrast
349
- // for content. Left at the template default; fine-tune manually if desired.
350
- bodyBgPrimary: FALLBACK_BASES.light.bodyBgPrimary,
351
- bodyBgSecondary: FALLBACK_BASES.light.bodyBgSecondary,
352
- };
353
- // Dark mode: same hues, slightly brighter for legibility over dark surfaces.
354
- const pDark = lighten(pLight, 0.08);
355
- const sDark = lighten(sLight, 0.12);
356
- const dark: BasicPalette = {
357
- primaryColor: pDark,
358
- primaryContrast: darken(pDark, 0.40),
359
- secondaryColor: sDark,
360
- secondaryContrast: contrastText(sDark),
361
- highlightColor: lighten(light.highlightColor, 0.10),
362
- bodyBgPrimary: FALLBACK_BASES.dark.bodyBgPrimary,
363
- bodyBgSecondary: FALLBACK_BASES.dark.bodyBgSecondary,
364
- };
365
-
366
- return { light, dark };
367
- };
@@ -1,22 +0,0 @@
1
-
2
- import { RGBColor } from 'react-color';
3
-
4
-
5
- export interface KeyValuePair {
6
- key: string;
7
- value: string;
8
- id: string;
9
- }
10
-
11
- export interface ColorFormat {
12
- hex: string;
13
- rgb: RGBColor;
14
- hsl: { h: number; s: number; l: number; a?: number };
15
- }
16
-
17
- export type ColorFormatType = 'hex' | 'rgb' | 'rgba' | 'hsl' | 'hsla';
18
-
19
- // Color mapping interface
20
- export interface ColorMapping {
21
- [key: string]: string;
22
- }
@@ -1,97 +0,0 @@
1
- import { useState, useEffect, useCallback } from 'react';
2
-
3
- interface ColorThiefResult {
4
- dominantColor: number[] | null;
5
- palette: number[][] | null;
6
- loading: boolean;
7
- error: string | null;
8
- }
9
-
10
- /**
11
- * Custom hook for async loading and using Color Thief functionality
12
- * @param imageSource - The image source (URL, base64, or ref)
13
- * @param options - Configuration options for color extraction
14
- * @returns Color thief result with dominant color and palette
15
- */
16
- export const useAsyncColorThief = (
17
- imageSource: string | null,
18
- options: { colorCount?: number; quality?: number } = {}
19
- ): ColorThiefResult => {
20
- const [result, setResult] = useState<ColorThiefResult>({
21
- dominantColor: null,
22
- palette: null,
23
- loading: false,
24
- error: null
25
- });
26
-
27
- const extractColors = useCallback(async (src: string) => {
28
- if (!src) return;
29
-
30
- setResult(prev => ({ ...prev, loading: true, error: null }));
31
-
32
- try {
33
- // Dynamically import ColorThief
34
- const ColorThief = (await import('colorthief')).default;
35
-
36
- // Create a temporary image element for color extraction
37
- const img = new Image();
38
- img.crossOrigin = 'anonymous';
39
-
40
- img.onload = () => {
41
- try {
42
- const colorThief = new ColorThief();
43
-
44
- const dominantColor = colorThief.getColor(img);
45
- const palette = colorThief.getPalette(img, options.colorCount || 5, options.quality || 10);
46
-
47
- setResult({
48
- dominantColor,
49
- palette,
50
- loading: false,
51
- error: null
52
- });
53
- } catch (error) {
54
- console.error('Color extraction error:', error);
55
- setResult(prev => ({
56
- ...prev,
57
- loading: false,
58
- error: `Failed to extract colors: ${error instanceof Error ? error.message : 'Unknown error'}`
59
- }));
60
- }
61
- };
62
-
63
- img.onerror = () => {
64
- setResult(prev => ({
65
- ...prev,
66
- loading: false,
67
- error: 'Failed to load image'
68
- }));
69
- };
70
-
71
- img.src = src;
72
- } catch (error) {
73
- console.error('ColorThief import error:', error);
74
- setResult(prev => ({
75
- ...prev,
76
- loading: false,
77
- error: `Failed to load Color Thief: ${error instanceof Error ? error.message : 'Unknown error'}`
78
- }));
79
- }
80
- }, [options.colorCount, options.quality]);
81
-
82
- useEffect(() => {
83
- if (imageSource) {
84
- extractColors(imageSource);
85
- } else {
86
- // Reset state when no image source
87
- setResult({
88
- dominantColor: null,
89
- palette: null,
90
- loading: false,
91
- error: null
92
- });
93
- }
94
- }, [imageSource, extractColors]);
95
-
96
- return result;
97
- };
@@ -1,106 +0,0 @@
1
- import React, { act, useCallback, useEffect, useState } from 'react';
2
- import { IDashAutoAdminCustomFieldComponent } from 'dash-auto-admin';
3
- /*import { ICommunes } from '@app/interfaces/ICommunes'; */
4
- import { useRecordContext, useUpdate } from 'react-admin';
5
- import { Switch, Box } from '@mui/material';
6
- import { FormControlLabel } from '@mui/material';
7
- import { AttributeToField } from 'dash-auto-admin/src/mui/AttributeToField';
8
- import AttributeToInput from 'dash-auto-admin/src/mui/AttributeToInput';
9
-
10
- export interface IListActive extends IDashAutoAdminCustomFieldComponent {
11
- activeLabel?: string;
12
- inactiveLabel?: string;
13
- enableLabel?: string;
14
- disableLabel?: string;
15
- }
16
-
17
- const ListActive = ({
18
- method,
19
- attribute,
20
- resourceConfig,
21
- activeLabel = 'Activo',
22
- inactiveLabel = 'Inactivo',
23
- enableLabel = 'Activar',
24
- disableLabel = 'Desactivar',
25
- showLabel = false,
26
- }: IListActive) => {
27
- const [ ,setLoading] = useState<boolean>(true);
28
- const [update, { isLoading: updateLoading }] = useUpdate();
29
- const record: any = useRecordContext();
30
- const [is_active, setIsActive] = useState<boolean>(false);
31
- const onError = (error: any) => {
32
- console.error(error);
33
- };
34
-
35
- const onChange = useCallback(
36
- async (value: boolean) => {
37
- /*window.dispatchEvent(
38
- new MessageEvent('dash-global-loader', { data: true })
39
- );*/
40
-
41
- try {
42
- await update(
43
- resourceConfig.model + '/partial/' + record.id,
44
- {
45
- id: record.id,
46
- data: { [attribute.attribute]: value },
47
- previousData: record,
48
- meta: {
49
- method: 'POST',
50
- }
51
- },
52
-
53
- {
54
- onSuccess: () => {
55
- // Force a refresh of the record context
56
- setIsActive(value);
57
- },
58
- onSettled: (data, error) => {
59
- if (error) onError(error);
60
- /* window.dispatchEvent(
61
- new MessageEvent('dash-global-loader', { data: false })
62
- );*/
63
- },
64
- }
65
- );
66
- } catch (error) {
67
- onError(error);
68
- }
69
- },
70
- [update, record]
71
- );
72
-
73
- useEffect(() => {
74
- setLoading(false);
75
-
76
- if (record && attribute && attribute.attribute in record) {
77
- setIsActive(!!record[attribute.attribute]);
78
- }
79
- }, [record, attribute]);
80
-
81
- //const textSwitch = record[attribute.attribute] ? disableLabel : enableLabel;
82
-
83
- switch (method) {
84
- case 'create':
85
- case 'edit':
86
- return AttributeToInput(method, resourceConfig, {...attribute,custom:false,type:Boolean})
87
- case 'view':
88
- return AttributeToField(method, resourceConfig, {...attribute,custom:false,type:Boolean})
89
- case 'list':
90
- return (
91
- <div>
92
- <Box>
93
- <Switch
94
- size='small'
95
- onChange={(e, value) => onChange(value)}
96
- checked={is_active}
97
- />{showLabel ? (is_active ? activeLabel : inactiveLabel) : <></>}
98
- </Box>
99
- </div>
100
- )
101
- default:
102
- return <>{attribute.label}: {is_active ? activeLabel : inactiveLabel}</>;
103
- }
104
- };
105
-
106
- export default ListActive;
@@ -1,96 +0,0 @@
1
- import React, { act, useCallback, useEffect, useState } from 'react';
2
- import { IDashAutoAdminCustomFieldComponent } from 'dash-auto-admin';
3
- /*import { ICommunes } from '@app/interfaces/ICommunes'; */
4
- import { useRecordContext, useUpdate } from 'react-admin';
5
- import { Switch, Box } from '@mui/material';
6
- import { FormControlLabel } from '@mui/material';
7
- import { AttributeToField } from 'dash-auto-admin/src/mui/AttributeToField';
8
- import AttributeToInput from 'dash-auto-admin/src/mui/AttributeToInput';
9
-
10
- export interface IListActive extends IDashAutoAdminCustomFieldComponent {
11
- activeLabel?: string;
12
- inactiveLabel?: string;
13
- enableLabel?: string;
14
- disableLabel?: string;
15
- }
16
-
17
- const ListActive = ({
18
- method,
19
- attribute,
20
- resourceConfig,
21
- activeLabel = 'Activo',
22
- inactiveLabel = 'Inactivo',
23
- enableLabel = 'Activar',
24
- disableLabel = 'Desactivar',
25
- }: IListActive) => {
26
- const [ ,setLoading] = useState<boolean>(true);
27
- const [update, { isLoading: updateLoading }] =
28
- useUpdate();
29
- const record: any = useRecordContext();
30
- const onError = (error: any) => {
31
- console.error(error);
32
- };
33
-
34
- const onChange = useCallback(
35
- async (value: boolean) => {
36
- window.dispatchEvent(
37
- new MessageEvent('dash-global-loader', { data: true })
38
- );
39
-
40
- try {
41
- await update(
42
- resourceConfig.model + '/change-status/' + record.id,
43
- {
44
- id: record.id,
45
- data: { is_active: value },
46
- previousData: record,
47
- },
48
- {
49
- onSuccess: () => {
50
- // Force a refresh of the record context
51
- record.is_active = value;
52
- },
53
- onSettled: (data, error) => {
54
- if (error) onError(error);
55
- window.dispatchEvent(
56
- new MessageEvent('dash-global-loader', { data: false })
57
- );
58
- },
59
- }
60
- );
61
- } catch (error) {
62
- onError(error);
63
- }
64
- },
65
- [update, record]
66
- );
67
-
68
- useEffect(() => {
69
- setLoading(false);
70
- }, [record]);
71
- const is_active = record?.is_active ? true : false;
72
- const textSwitch = record?.is_active ? disableLabel : enableLabel;
73
- switch (method) {
74
- case 'create':
75
- case 'edit':
76
- return AttributeToInput(method, resourceConfig, {...attribute,custom:false,type:Boolean})
77
- case 'view':
78
- return AttributeToField(method, resourceConfig, {...attribute,custom:false,type:Boolean})
79
- case 'list':
80
- return (
81
- <div>
82
- <Box>
83
- <Switch
84
-
85
- onChange={(e, value) => onChange(value)}
86
- {...(is_active === true && { defaultChecked: true })}
87
- />{is_active ? activeLabel : inactiveLabel}
88
- </Box>
89
- </div>
90
- )
91
- default:
92
- return <>{attribute.label}: {is_active ? activeLabel : inactiveLabel}</>;
93
- }
94
- };
95
-
96
- export default ListActive;