@indielayer/ui 1.0.0-alpha.0 → 1.0.0-alpha.5

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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -72
  3. package/lib/components/avatar/Avatar.vue.d.ts +2 -2
  4. package/lib/components/badge/Badge.vue.d.ts +2 -2
  5. package/lib/components/button/Button.vue.d.ts +2 -2
  6. package/lib/components/button/ButtonGroup.vue.d.ts +2 -2
  7. package/lib/components/checkbox/Checkbox.vue.d.ts +4 -3
  8. package/lib/components/drawer/Drawer.vue.d.ts +2 -2
  9. package/lib/components/icon/Icon.vue.d.ts +7 -3
  10. package/lib/components/index.d.ts +2 -2
  11. package/lib/components/input/Input.vue.d.ts +3 -2
  12. package/lib/components/menu/Menu.vue.d.ts +2 -2
  13. package/lib/components/menu/MenuItem.vue.d.ts +3 -3
  14. package/lib/components/notifications/Notifications.vue.d.ts +2 -2
  15. package/lib/components/pagination/Pagination.vue.d.ts +3 -2
  16. package/lib/components/pagination/PaginationItem.vue.d.ts +2 -2
  17. package/lib/components/radio/Radio.vue.d.ts +2 -2
  18. package/lib/components/select/Select.vue.d.ts +3 -2
  19. package/lib/components/slider/Slider.vue.d.ts +2 -2
  20. package/lib/components/spacer/Spacer.vue.d.ts +1 -1
  21. package/lib/components/spinner/Spinner.vue.d.ts +2 -2
  22. package/lib/components/{tabs → tab}/Tab.vue.d.ts +2 -2
  23. package/lib/components/{tabs/Tabs.vue.d.ts → tab/TabGroup.vue.d.ts} +0 -0
  24. package/lib/components/table/TableBody.vue.d.ts +1 -1
  25. package/lib/components/table/TableHead.vue.d.ts +1 -1
  26. package/lib/components/tag/Tag.vue.d.ts +2 -2
  27. package/lib/components/textarea/Textarea.vue.d.ts +3 -11
  28. package/lib/components/toggle/Toggle.vue.d.ts +2 -2
  29. package/lib/composables/keys.d.ts +1 -0
  30. package/lib/create.d.ts +12 -0
  31. package/lib/index.cjs.js +2 -2
  32. package/lib/index.d.ts +2 -0
  33. package/lib/index.es.js +271 -130
  34. package/lib/install.d.ts +4 -6
  35. package/lib/nuxt.js +15 -16
  36. package/lib/nuxt.plugin.js +8 -0
  37. package/lib/style.css +1 -1
  38. package/lib/version.d.ts +1 -1
  39. package/package.json +21 -15
  40. package/src/components/alert/Alert.vue +164 -0
  41. package/src/components/avatar/Avatar.vue +137 -0
  42. package/src/components/badge/Badge.vue +107 -0
  43. package/src/components/breadcrumbs/Breadcrumbs.vue +60 -0
  44. package/src/components/button/Button.vue +433 -0
  45. package/src/components/button/ButtonGroup.vue +73 -0
  46. package/src/components/card/Card.vue +25 -0
  47. package/src/components/checkbox/Checkbox.vue +205 -0
  48. package/src/components/collapse/Collapse.vue +181 -0
  49. package/src/components/container/Container.vue +23 -0
  50. package/src/components/divider/Divider.vue +52 -0
  51. package/src/components/drawer/Drawer.vue +244 -0
  52. package/src/components/form/Form.vue +111 -0
  53. package/src/components/icon/Icon.vue +123 -0
  54. package/src/components/image/Image.vue +36 -0
  55. package/src/components/index.ts +45 -0
  56. package/src/components/input/Input.vue +199 -0
  57. package/src/components/link/Link.vue +110 -0
  58. package/src/components/menu/Menu.vue +118 -0
  59. package/src/components/menu/MenuItem.vue +277 -0
  60. package/src/components/modal/Modal.vue +175 -0
  61. package/src/components/notifications/Notifications.vue +318 -0
  62. package/src/components/pagination/Pagination.vue +181 -0
  63. package/src/components/pagination/PaginationItem.vue +58 -0
  64. package/src/components/popover/Popover.vue +194 -0
  65. package/src/components/popover/PopoverContainer.vue +23 -0
  66. package/src/components/progress/Progress.vue +86 -0
  67. package/src/components/radio/Radio.vue +220 -0
  68. package/src/components/scroll/Scroll.vue +143 -0
  69. package/src/components/select/Select.vue +408 -0
  70. package/src/components/skeleton/Skeleton.vue +23 -0
  71. package/src/components/slider/Slider.vue +240 -0
  72. package/src/components/spacer/Spacer.vue +11 -0
  73. package/src/components/spinner/Spinner.vue +45 -0
  74. package/src/components/tab/Tab.vue +100 -0
  75. package/src/components/tab/TabGroup.vue +151 -0
  76. package/src/components/table/Table.vue +172 -0
  77. package/src/components/table/TableBody.vue +13 -0
  78. package/src/components/table/TableCell.vue +78 -0
  79. package/src/components/table/TableHead.vue +15 -0
  80. package/src/components/table/TableHeader.vue +94 -0
  81. package/src/components/table/TableRow.vue +43 -0
  82. package/src/components/tag/Tag.vue +98 -0
  83. package/src/components/textarea/Textarea.vue +156 -0
  84. package/src/components/toggle/Toggle.vue +144 -0
  85. package/src/components/tooltip/Tooltip.vue +26 -0
  86. package/src/composables/colors-utils.ts +378 -0
  87. package/src/composables/colors.ts +82 -0
  88. package/src/composables/common.ts +20 -0
  89. package/src/composables/css.ts +45 -0
  90. package/src/composables/index.ts +7 -0
  91. package/src/composables/inputtable.ts +128 -0
  92. package/src/composables/interactive.ts +16 -0
  93. package/src/composables/keys.ts +8 -0
  94. package/src/composables/notification.ts +10 -0
  95. package/src/create.ts +38 -0
  96. package/src/exports/nuxt.js +32 -0
  97. package/src/exports/nuxt.plugin.js +8 -0
  98. package/src/exports/tailwind.preset.js +55 -0
  99. package/src/index.ts +8 -0
  100. package/src/install.ts +8 -0
  101. package/src/shims-vue.d.ts +6 -0
  102. package/src/version.ts +1 -0
  103. package/volar.d.ts +1 -1
@@ -0,0 +1,378 @@
1
+ import type { Tone, ColorLibrary, ColorPalette } from './colors'
2
+
3
+ const isHex = (hex: string) => /^#(?:[A-Fa-f0-9]{3}){1,2}$/.test(hex)
4
+ const isRGB = (rgb: string) => /^rgb[(](?:\s*0*(?:\d\d?(?:\.\d+)?(?:\s*%)?|\.\d+\s*%|100(?:\.0*)?\s*%|(?:1\d\d|2[0-4]\d|25[0-5])(?:\.\d+)?)\s*(?:,(?![)])|(?=[)]))){3}[)]$/.test(rgb)
5
+ const isRGBA = (rgba: string) => /^^rgba[(](?:\s*0*(?:\d\d?(?:\.\d+)?(?:\s*%)?|\.\d+\s*%|100(?:\.0*)?\s*%|(?:1\d\d|2[0-4]\d|25[0-5])(?:\.\d+)?)\s*,){3}\s*0*(?:\.\d+|1(?:\.0*)?)\s*[)]$/.test(rgba)
6
+ const parseRGB = (rgb: string) => rgb.match(/(?<=\().+?(?=\))/g)?.[0].split(',')
7
+ const hexToRGB = (hex: string) => hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (m, r, g, b) => '#' + r + r + g + g + b + b)
8
+ .substring(1).match(/.{2}/g)
9
+ ?.map((x) => parseInt(x, 16))
10
+
11
+ export const setOpacity = (color: string, opacity: number) => {
12
+ const [r, g, b] = (isHex(color) ? hexToRGB(color) : parseRGB(color)) ?? [0,0,0]
13
+
14
+ return 'rgba' + '(' + r + ',' + g + ',' + b + ',' + opacity + ')'
15
+ }
16
+
17
+ export const isValidColor = (color: string) => isHex(color) || isRGB(color) || isRGBA(color)
18
+
19
+ export const colorShade = (color: string, percentage: number) => {
20
+ const lighten = percentage < 0
21
+ const base = lighten ? 1 + percentage : 1 - percentage
22
+ const shade = lighten ? 0 : percentage * 255 ** 2
23
+ const calcPrimary = (p: string | number) => Math.round((base * Math.floor(Number(p)) ** 2 + shade) ** 0.5)
24
+
25
+ const [r, g, b, a] = (isHex(color) ? hexToRGB(color) : parseRGB(color)) ?? [0,0,0]
26
+ const red = calcPrimary(r)
27
+ const green = calcPrimary(g)
28
+ const blue = calcPrimary(b)
29
+
30
+ return 'rgb' + (a ? 'a(' : '(') + red + ',' + green + ',' + blue + (a ? ',' + a : ')')
31
+ }
32
+
33
+ export const shades: Tone[] = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900']
34
+ export const indielayerColors = ['primary', 'secondary', 'success', 'warning', 'error']
35
+
36
+ // calculate custom colors
37
+ export function calculateColors(): ColorLibrary {
38
+ const cc = computedColors
39
+ const customColors: ColorLibrary = {}
40
+ const e = document.createElement('div')
41
+
42
+ document.body.appendChild(e)
43
+
44
+ indielayerColors.forEach((color) => {
45
+ const c: ColorPalette = { ...tailwindColors.gray }
46
+
47
+ shades.forEach((shade) => {
48
+ e.className = `bg-${color}-${shade}`
49
+ c[shade] = window.getComputedStyle(e ,null).getPropertyValue('background-color')
50
+ })
51
+
52
+ customColors[color] = c
53
+ })
54
+
55
+ e.remove()
56
+
57
+ return customColors
58
+ }
59
+
60
+ const computedColors = Object.freeze([
61
+ 'bg-primary-50',
62
+ 'bg-primary-100',
63
+ 'bg-primary-200',
64
+ 'bg-primary-300',
65
+ 'bg-primary-400',
66
+ 'bg-primary-500',
67
+ 'bg-primary-600',
68
+ 'bg-primary-700',
69
+ 'bg-primary-800',
70
+ 'bg-primary-900',
71
+ 'bg-secondary-50',
72
+ 'bg-secondary-100',
73
+ 'bg-secondary-200',
74
+ 'bg-secondary-300',
75
+ 'bg-secondary-400',
76
+ 'bg-secondary-500',
77
+ 'bg-secondary-600',
78
+ 'bg-secondary-700',
79
+ 'bg-secondary-800',
80
+ 'bg-secondary-900',
81
+ 'bg-error-50',
82
+ 'bg-error-100',
83
+ 'bg-error-200',
84
+ 'bg-error-300',
85
+ 'bg-error-400',
86
+ 'bg-error-500',
87
+ 'bg-error-600',
88
+ 'bg-error-700',
89
+ 'bg-error-800',
90
+ 'bg-error-900',
91
+ 'bg-warning-50',
92
+ 'bg-warning-100',
93
+ 'bg-warning-200',
94
+ 'bg-warning-300',
95
+ 'bg-warning-400',
96
+ 'bg-warning-500',
97
+ 'bg-warning-600',
98
+ 'bg-warning-700',
99
+ 'bg-warning-800',
100
+ 'bg-warning-900',
101
+ 'bg-success-50',
102
+ 'bg-success-100',
103
+ 'bg-success-200',
104
+ 'bg-success-300',
105
+ 'bg-success-400',
106
+ 'bg-success-500',
107
+ 'bg-success-600',
108
+ 'bg-success-700',
109
+ 'bg-success-800',
110
+ 'bg-success-900',
111
+ ])
112
+
113
+ export const tailwindColors: ColorLibrary = Object.freeze({
114
+ slate: {
115
+ 50: '#f8fafc',
116
+ 100: '#f1f5f9',
117
+ 200: '#e2e8f0',
118
+ 300: '#cbd5e1',
119
+ 400: '#94a3b8',
120
+ 500: '#64748b',
121
+ 600: '#475569',
122
+ 700: '#334155',
123
+ 800: '#1e293b',
124
+ 900: '#0f172a',
125
+ },
126
+ gray: {
127
+ 50: '#f9fafb',
128
+ 100: '#f3f4f6',
129
+ 200: '#e5e7eb',
130
+ 300: '#d1d5db',
131
+ 400: '#9ca3af',
132
+ 500: '#6b7280',
133
+ 600: '#4b5563',
134
+ 700: '#374151',
135
+ 800: '#1f2937',
136
+ 900: '#111827',
137
+ },
138
+ zinc: {
139
+ 50: '#fafafa',
140
+ 100: '#f4f4f5',
141
+ 200: '#e4e4e7',
142
+ 300: '#d4d4d8',
143
+ 400: '#a1a1aa',
144
+ 500: '#71717a',
145
+ 600: '#52525b',
146
+ 700: '#3f3f46',
147
+ 800: '#27272a',
148
+ 900: '#18181b',
149
+ },
150
+ neutral: {
151
+ 50: '#fafafa',
152
+ 100: '#f5f5f5',
153
+ 200: '#e5e5e5',
154
+ 300: '#d4d4d4',
155
+ 400: '#a3a3a3',
156
+ 500: '#737373',
157
+ 600: '#525252',
158
+ 700: '#404040',
159
+ 800: '#262626',
160
+ 900: '#171717',
161
+ },
162
+ stone: {
163
+ 50: '#fafaf9',
164
+ 100: '#f5f5f4',
165
+ 200: '#e7e5e4',
166
+ 300: '#d6d3d1',
167
+ 400: '#a8a29e',
168
+ 500: '#78716c',
169
+ 600: '#57534e',
170
+ 700: '#44403c',
171
+ 800: '#292524',
172
+ 900: '#1c1917',
173
+ },
174
+ red: {
175
+ 50: '#fef2f2',
176
+ 100: '#fee2e2',
177
+ 200: '#fecaca',
178
+ 300: '#fca5a5',
179
+ 400: '#f87171',
180
+ 500: '#ef4444',
181
+ 600: '#dc2626',
182
+ 700: '#b91c1c',
183
+ 800: '#991b1b',
184
+ 900: '#7f1d1d',
185
+ },
186
+ orange: {
187
+ 50: '#fff7ed',
188
+ 100: '#ffedd5',
189
+ 200: '#fed7aa',
190
+ 300: '#fdba74',
191
+ 400: '#fb923c',
192
+ 500: '#f97316',
193
+ 600: '#ea580c',
194
+ 700: '#c2410c',
195
+ 800: '#9a3412',
196
+ 900: '#7c2d12',
197
+ },
198
+ amber: {
199
+ 50: '#fffbeb',
200
+ 100: '#fef3c7',
201
+ 200: '#fde68a',
202
+ 300: '#fcd34d',
203
+ 400: '#fbbf24',
204
+ 500: '#f59e0b',
205
+ 600: '#d97706',
206
+ 700: '#b45309',
207
+ 800: '#92400e',
208
+ 900: '#78350f',
209
+ },
210
+ yellow: {
211
+ 50: '#fefce8',
212
+ 100: '#fef9c3',
213
+ 200: '#fef08a',
214
+ 300: '#fde047',
215
+ 400: '#facc15',
216
+ 500: '#eab308',
217
+ 600: '#ca8a04',
218
+ 700: '#a16207',
219
+ 800: '#854d0e',
220
+ 900: '#713f12',
221
+ },
222
+ lime: {
223
+ 50: '#f7fee7',
224
+ 100: '#ecfccb',
225
+ 200: '#d9f99d',
226
+ 300: '#bef264',
227
+ 400: '#a3e635',
228
+ 500: '#84cc16',
229
+ 600: '#65a30d',
230
+ 700: '#4d7c0f',
231
+ 800: '#3f6212',
232
+ 900: '#365314',
233
+ },
234
+ green: {
235
+ 50: '#f0fdf4',
236
+ 100: '#dcfce7',
237
+ 200: '#bbf7d0',
238
+ 300: '#86efac',
239
+ 400: '#4ade80',
240
+ 500: '#22c55e',
241
+ 600: '#16a34a',
242
+ 700: '#15803d',
243
+ 800: '#166534',
244
+ 900: '#14532d',
245
+ },
246
+ emerald: {
247
+ 50: '#ecfdf5',
248
+ 100: '#d1fae5',
249
+ 200: '#a7f3d0',
250
+ 300: '#6ee7b7',
251
+ 400: '#34d399',
252
+ 500: '#10b981',
253
+ 600: '#059669',
254
+ 700: '#047857',
255
+ 800: '#065f46',
256
+ 900: '#064e3b',
257
+ },
258
+ teal: {
259
+ 50: '#f0fdfa',
260
+ 100: '#ccfbf1',
261
+ 200: '#99f6e4',
262
+ 300: '#5eead4',
263
+ 400: '#2dd4bf',
264
+ 500: '#14b8a6',
265
+ 600: '#0d9488',
266
+ 700: '#0f766e',
267
+ 800: '#115e59',
268
+ 900: '#134e4a',
269
+ },
270
+ cyan: {
271
+ 50: '#ecfeff',
272
+ 100: '#cffafe',
273
+ 200: '#a5f3fc',
274
+ 300: '#67e8f9',
275
+ 400: '#22d3ee',
276
+ 500: '#06b6d4',
277
+ 600: '#0891b2',
278
+ 700: '#0e7490',
279
+ 800: '#155e75',
280
+ 900: '#164e63',
281
+ },
282
+ sky: {
283
+ 50: '#f0f9ff',
284
+ 100: '#e0f2fe',
285
+ 200: '#bae6fd',
286
+ 300: '#7dd3fc',
287
+ 400: '#38bdf8',
288
+ 500: '#0ea5e9',
289
+ 600: '#0284c7',
290
+ 700: '#0369a1',
291
+ 800: '#075985',
292
+ 900: '#0c4a6e',
293
+ },
294
+ blue: {
295
+ 50: '#eff6ff',
296
+ 100: '#dbeafe',
297
+ 200: '#bfdbfe',
298
+ 300: '#93c5fd',
299
+ 400: '#60a5fa',
300
+ 500: '#3b82f6',
301
+ 600: '#2563eb',
302
+ 700: '#1d4ed8',
303
+ 800: '#1e40af',
304
+ 900: '#1e3a8a',
305
+ },
306
+ indigo: {
307
+ 50: '#eef2ff',
308
+ 100: '#e0e7ff',
309
+ 200: '#c7d2fe',
310
+ 300: '#a5b4fc',
311
+ 400: '#818cf8',
312
+ 500: '#6366f1',
313
+ 600: '#4f46e5',
314
+ 700: '#4338ca',
315
+ 800: '#3730a3',
316
+ 900: '#312e81',
317
+ },
318
+ violet: {
319
+ 50: '#f5f3ff',
320
+ 100: '#ede9fe',
321
+ 200: '#ddd6fe',
322
+ 300: '#c4b5fd',
323
+ 400: '#a78bfa',
324
+ 500: '#8b5cf6',
325
+ 600: '#7c3aed',
326
+ 700: '#6d28d9',
327
+ 800: '#5b21b6',
328
+ 900: '#4c1d95',
329
+ },
330
+ purple: {
331
+ 50: '#faf5ff',
332
+ 100: '#f3e8ff',
333
+ 200: '#e9d5ff',
334
+ 300: '#d8b4fe',
335
+ 400: '#c084fc',
336
+ 500: '#a855f7',
337
+ 600: '#9333ea',
338
+ 700: '#7e22ce',
339
+ 800: '#6b21a8',
340
+ 900: '#581c87',
341
+ },
342
+ fuchsia: {
343
+ 50: '#fdf4ff',
344
+ 100: '#fae8ff',
345
+ 200: '#f5d0fe',
346
+ 300: '#f0abfc',
347
+ 400: '#e879f9',
348
+ 500: '#d946ef',
349
+ 600: '#c026d3',
350
+ 700: '#a21caf',
351
+ 800: '#86198f',
352
+ 900: '#701a75',
353
+ },
354
+ pink: {
355
+ 50: '#fdf2f8',
356
+ 100: '#fce7f3',
357
+ 200: '#fbcfe8',
358
+ 300: '#f9a8d4',
359
+ 400: '#f472b6',
360
+ 500: '#ec4899',
361
+ 600: '#db2777',
362
+ 700: '#be185d',
363
+ 800: '#9d174d',
364
+ 900: '#831843',
365
+ },
366
+ rose: {
367
+ 50: '#fff1f2',
368
+ 100: '#ffe4e6',
369
+ 200: '#fecdd3',
370
+ 300: '#fda4af',
371
+ 400: '#fb7185',
372
+ 500: '#f43f5e',
373
+ 600: '#e11d48',
374
+ 700: '#be123c',
375
+ 800: '#9f1239',
376
+ 900: '#881337',
377
+ },
378
+ })
@@ -0,0 +1,82 @@
1
+ import { inject } from 'vue'
2
+ import { injectColorsKey } from './keys'
3
+ import { isValidColor, tailwindColors, colorShade, setOpacity } from './colors-utils'
4
+
5
+ export type Tone = '50' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'
6
+
7
+ export interface ColorPalette {
8
+ 50: string
9
+ 100: string
10
+ 200: string
11
+ 300: string
12
+ 400: string
13
+ 500: string
14
+ 600: string
15
+ 700: string
16
+ 800: string
17
+ 900: string
18
+ }
19
+
20
+ export type ColorLibrary = Record<string, ColorPalette>
21
+
22
+ const colorCache: ColorLibrary = {}
23
+
24
+ const defaultColors = {
25
+ primary: tailwindColors.sky,
26
+ secondary: tailwindColors.slate,
27
+ success: tailwindColors.green,
28
+ warning: tailwindColors.yellow,
29
+ error: tailwindColors.red,
30
+ }
31
+
32
+ export const useColors = () => {
33
+ const customColors = inject(injectColorsKey) || defaultColors
34
+ // if (Object.keys(customColors).length === 0) customColors = calculateColors()
35
+
36
+ const getTailwindColor = (color: string) => tailwindColors[color]
37
+
38
+ const getColorOpacity = (color: string, opacity: number) => setOpacity(color, opacity)
39
+
40
+ const getPalette = (color: string): ColorPalette => {
41
+ const twColor = getTailwindColor(color)
42
+
43
+ if (twColor) return twColor
44
+ if (colorCache[color]) return colorCache[color]
45
+ if (customColors[color]) return customColors[color]
46
+
47
+ if (!isValidColor(color)) {
48
+ console.warn(`Invalid color: ${color}`)
49
+
50
+ return getTailwindColor('gray')
51
+ }
52
+
53
+ const palette = {
54
+ 50: colorShade(color, 0.9),
55
+ 100: colorShade(color, 0.8),
56
+ 200: colorShade(color, 0.6),
57
+ 300: colorShade(color, 0.4),
58
+ 400: colorShade(color, 0.1),
59
+ 500: color,
60
+ 600: colorShade(color, -0.1),
61
+ 700: colorShade(color, -0.25),
62
+ 800: colorShade(color, -0.58),
63
+ 900: colorShade(color, -0.7),
64
+ }
65
+
66
+ colorCache[color] = palette
67
+
68
+ return palette
69
+ }
70
+
71
+ return {
72
+ getPalette,
73
+ getColorOpacity,
74
+ }
75
+ }
76
+
77
+ useColors.props = (defaultColor?: string) => ({
78
+ color: {
79
+ type: String,
80
+ default: defaultColor,
81
+ },
82
+ } as const)
@@ -0,0 +1,20 @@
1
+ import type { PropType } from 'vue'
2
+
3
+ export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | undefined
4
+
5
+ export const useCommon = () => {}
6
+
7
+ const validators = Object.freeze({
8
+ size: ['xs', 'sm', 'md', 'lg', 'xl'],
9
+ })
10
+
11
+ useCommon.props = () => ({
12
+ size: {
13
+ type: String as PropType<Size>,
14
+ validator: (value: string) => validators.size.includes(value),
15
+ },
16
+ } as const)
17
+
18
+ useCommon.validators = () => ({
19
+ ...validators,
20
+ })
@@ -0,0 +1,45 @@
1
+ const themes = ['dark']
2
+ const modifiers = ['hover', 'active', 'focus', 'visited']
3
+
4
+ const isTheme = (theme: string) => themes.includes(theme)
5
+ const isModifier = (modifier: string) => modifiers.includes(modifier)
6
+
7
+ export const useCSS = (namespace?: string) => {
8
+
9
+ const get = (name: string, value: string, theme?: string, modifier?: string) => `${variable(name,theme,modifier)}: ${value}`
10
+
11
+ const variable = (name: string, theme?: string, modifier?: string) =>
12
+ `--x${theme ? `-${theme}` : ''}${namespace ? `-${namespace}` : ''}-${name}${modifier ? `-${modifier}` : ''}`
13
+
14
+ const variables = (object: Record<string, string | object>, theme?: string, modifier?: string) => {
15
+ let styles: Record<string, string> = {}
16
+
17
+ for (const key in object) {
18
+ const keyValue = object[key]
19
+
20
+ if (!keyValue) break
21
+
22
+ if (isTheme(key)) {
23
+ styles = {
24
+ ...styles,
25
+ ...variables(<any>keyValue, key, modifier),
26
+ }
27
+ } else if (isModifier(key)) {
28
+ styles = {
29
+ ...styles,
30
+ ...variables(<any>keyValue, theme, key),
31
+ }
32
+ } else {
33
+ styles[variable(key, theme, modifier)] = <string>keyValue
34
+ }
35
+ }
36
+
37
+ return styles
38
+ }
39
+
40
+ return {
41
+ get,
42
+ variable,
43
+ variables,
44
+ }
45
+ }
@@ -0,0 +1,7 @@
1
+ export * from './keys'
2
+ export * from './common'
3
+ export * from './colors'
4
+ export * from './css'
5
+ export * from './inputtable'
6
+ export * from './interactive'
7
+ export * from './notification'
@@ -0,0 +1,128 @@
1
+ import type { Ref, PropType } from 'vue'
2
+ import { ref, computed, inject, watch, onMounted, onUnmounted } from 'vue'
3
+ import { injectFormKey } from './keys'
4
+
5
+ export interface XFormInputMethods {
6
+ focus: ()=> void,
7
+ validate: (val: any)=> boolean,
8
+ setError: (val: string)=> void
9
+ }
10
+
11
+ export const useInputtable = (props: any, { focus, emit, withListeners = true }: { focus: ()=> void, emit: any, withListeners?: boolean }) => {
12
+ const isFirstValidation = ref(true)
13
+ const errorInternal = ref(props.error)
14
+
15
+ const name = props.name ? props.name : (Math.random() + 1).toString(36).substring(7)
16
+ const nameInternal = ref(name)
17
+
18
+ watch(() => props.error, (val) => { errorInternal.value = val })
19
+ watch(() => props.name, (val) => { if (val) nameInternal.value = val })
20
+
21
+ const form = inject(injectFormKey, {
22
+ registerInput: (inputName: string, methods: XFormInputMethods) => {},
23
+ unregisterInput: (inputName: string) => {},
24
+ isInsideForm: false,
25
+ })
26
+
27
+ const reset = () => {
28
+ errorInternal.value = ''
29
+ isFirstValidation.value = true
30
+ emit('update:modelValue', '')
31
+ }
32
+
33
+ const setError = (val: string) => {
34
+ errorInternal.value = val
35
+ }
36
+
37
+ const validate = (val: any): boolean => {
38
+ val = val || props.modelValue
39
+
40
+ isFirstValidation.value = false
41
+
42
+ for (let i = 0; i < props.rules.length; i++) {
43
+ const item = props.rules[i]
44
+
45
+ let isValid = true
46
+
47
+ // Direct Function
48
+ if (typeof item === 'function') {
49
+ const rule = item
50
+
51
+ isValid = rule(val)
52
+ } else if (Array.isArray(item) && item.length === 2) {
53
+ // Rule array [function, options]
54
+ const { 0: rule, 1: options } = item
55
+
56
+ isValid = rule(val, options)
57
+ } else {
58
+ // Rule object { fn, options }
59
+ const rule = item.fn
60
+ const { options } = item
61
+
62
+ isValid = rule(val, options)
63
+ }
64
+
65
+ if (isValid !== true) {
66
+ errorInternal.value = isValid
67
+
68
+ return false
69
+ }
70
+ }
71
+
72
+ errorInternal.value = ''
73
+
74
+ return true
75
+ }
76
+
77
+ const inputListeners = withListeners ? computed(() => {
78
+ return {
79
+ blur: (event: Event) => emit('blur', event),
80
+ focus: (event: Event) => emit('focus', event),
81
+ input: (event: Event) => {
82
+ if (props.validateOnInput && !isFirstValidation.value) validate((event.target as HTMLInputElement).value)
83
+ emit('update:modelValue', (event.target as HTMLInputElement).value)
84
+ },
85
+ change: (event: Event) => emit('change', event),
86
+ }
87
+ }) : {}
88
+
89
+ onMounted(() => {
90
+ form.registerInput(nameInternal.value, focus, validate, setError)
91
+ })
92
+
93
+ onUnmounted(() => {
94
+ form.unregisterInput(nameInternal.value)
95
+ })
96
+
97
+ return {
98
+ isFirstValidation,
99
+ errorInternal,
100
+ isInsideForm: form.isInsideForm,
101
+ inputListeners,
102
+ reset,
103
+ validate,
104
+ setError,
105
+ }
106
+ }
107
+
108
+ useInputtable.emits = (withListeners = true): string[] => {
109
+ return withListeners ?
110
+ ['update:modelValue', 'blur', 'focus', 'input', 'change'] :
111
+ ['update:modelValue']
112
+ }
113
+
114
+ useInputtable.props = () => ({
115
+ modelValue: [String, Number, Boolean, Object, Array] as PropType<[string, number, boolean, object, []]>,
116
+ name: String,
117
+ readonly: Boolean,
118
+ required: Boolean,
119
+ validateOnInput: {
120
+ type: Boolean,
121
+ default: true,
122
+ },
123
+ error: String,
124
+ rules: {
125
+ type: Array,
126
+ default: () => [],
127
+ },
128
+ } as const)
@@ -0,0 +1,16 @@
1
+ import type { Ref } from 'vue'
2
+
3
+ export const useInteractive = (
4
+ el: Ref<HTMLElement | undefined>,
5
+ ) => {
6
+ return {
7
+ focus: () => {
8
+ el.value?.focus?.()
9
+ },
10
+ }
11
+ }
12
+
13
+ useInteractive.props = () => ({
14
+ disabled: Boolean,
15
+ loading: Boolean,
16
+ } as const)
@@ -0,0 +1,8 @@
1
+ import type { InjectionKey } from 'vue'
2
+
3
+ export const injectTabKey = Symbol() as InjectionKey<any>
4
+ export const injectFormKey = Symbol() as InjectionKey<any>
5
+ export const injectIconsKey = Symbol() as InjectionKey<any>
6
+ export const injectColorsKey = Symbol() as InjectionKey<any>
7
+ export const injectButtonGroupKey = Symbol() as InjectionKey<any>
8
+ export const injectNotificationKey = Symbol() as InjectionKey<any>
@@ -0,0 +1,10 @@
1
+ import { inject } from 'vue'
2
+ import { injectNotificationKey } from './keys'
3
+
4
+ export const useNotification = () => {
5
+ const notification = inject(injectNotificationKey)
6
+
7
+ if (!notification) console.warn('useNotification must have a parent wrapped with Notifications component')
8
+
9
+ return notification
10
+ }