@1001-digital/components 1.5.0 → 2.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1001-digital/components",
3
- "version": "1.5.0",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "sideEffects": [
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "peerDependencies": {
17
17
  "vue": "^3.5.0",
18
- "@1001-digital/styles": "^1.3.0"
18
+ "@1001-digital/styles": "^2.0.0"
19
19
  },
20
20
  "dependencies": {
21
21
  "@iconify/vue": "^5.0.0",
@@ -10,7 +10,7 @@
10
10
  @click="dismiss"
11
11
  class="close"
12
12
  >
13
- <Icon type="close" />
13
+ <Icon name="close" />
14
14
  </button>
15
15
  <slot />
16
16
  </aside>
@@ -46,7 +46,7 @@ const dismiss = () => {
46
46
  gap: var(--spacer-sm);
47
47
  border: var(--border);
48
48
  border-color: var(--alert-border-color);
49
- background-color: var(--alert-background-color);
49
+ background-color: var(--alert-background);
50
50
  color: var(--alert-color);
51
51
  font-family: var(--font-family);
52
52
  font-size: var(--ui-font-size);
@@ -39,23 +39,22 @@ const sidebarOpen = defineModel<boolean>('sidebarOpen', { default: false })
39
39
 
40
40
  <style>
41
41
  @layer components {
42
- html:has(.app-shell) {
43
- scrollbar-gutter: auto;
44
- overflow: hidden;
45
- height: 100dvh;
46
- }
47
-
48
42
  .app-shell {
49
43
  display: flex;
50
- block-size: 100dvh;
51
- overflow: hidden;
44
+ min-block-size: 100dvh;
45
+ }
46
+
47
+ html:has(.app-shell nav.bottom-nav) > body {
48
+ border-inline-end: var(--border);
49
+
50
+ .app-shell nav.bottom-nav {
51
+ border-inline-end: var(--border);
52
+ }
52
53
  }
53
54
 
54
55
  .app-shell-main {
55
56
  flex: 1;
56
57
  min-inline-size: 0;
57
- overflow-y: auto;
58
- overscroll-behavior-y: contain;
59
58
  padding-block-start: env(safe-area-inset-top);
60
59
 
61
60
  &:has(+ nav.bottom-nav) {
@@ -18,11 +18,11 @@
18
18
  >
19
19
  <CalendarHeader class="calendar-header">
20
20
  <CalendarPrev class="calendar-nav">
21
- <Icon type="chevron-left" />
21
+ <Icon name="chevron-left" />
22
22
  </CalendarPrev>
23
23
  <CalendarHeading class="calendar-heading" />
24
24
  <CalendarNext class="calendar-nav">
25
- <Icon type="chevron-right" />
25
+ <Icon name="chevron-right" />
26
26
  </CalendarNext>
27
27
  </CalendarHeader>
28
28
 
@@ -0,0 +1,318 @@
1
+ <template>
2
+ <Popover
3
+ v-model:open="open"
4
+ :side="side"
5
+ :align="align"
6
+ :side-offset="sideOffset"
7
+ class="color-picker-popover"
8
+ >
9
+ <template #trigger>
10
+ <button
11
+ class="color-picker-trigger"
12
+ type="button"
13
+ >
14
+ <ColorSwatch
15
+ :color="hexColor"
16
+ class="color-picker-swatch"
17
+ />
18
+ <span class="color-picker-value">{{ hexColor }}</span>
19
+ </button>
20
+ </template>
21
+
22
+ <div class="color-picker">
23
+ <!-- 2D Color Area (Saturation/Lightness) -->
24
+ <ColorAreaRoot
25
+ v-slot="{ style }"
26
+ :model-value="colorObj"
27
+ color-space="hsl"
28
+ x-channel="saturation"
29
+ y-channel="lightness"
30
+ class="color-picker-area"
31
+ @update:color="handleColorUpdate"
32
+ >
33
+ <ColorAreaArea
34
+ class="color-picker-area-surface"
35
+ :style="style"
36
+ >
37
+ <ColorAreaThumb class="color-picker-thumb" />
38
+ </ColorAreaArea>
39
+ </ColorAreaRoot>
40
+
41
+ <!-- Hue Slider -->
42
+ <ColorSliderRoot
43
+ :model-value="colorObj"
44
+ channel="hue"
45
+ color-space="hsl"
46
+ class="color-picker-slider"
47
+ @update:color="handleColorUpdate"
48
+ >
49
+ <ColorSliderTrack class="color-picker-slider-track">
50
+ <div class="color-picker-slider-track-fill" />
51
+ </ColorSliderTrack>
52
+ <ColorSliderThumb class="color-picker-thumb" />
53
+ </ColorSliderRoot>
54
+
55
+ <!-- Alpha Slider -->
56
+ <ColorSliderRoot
57
+ v-if="alpha"
58
+ :model-value="colorObj"
59
+ channel="alpha"
60
+ color-space="hsl"
61
+ class="color-picker-slider"
62
+ @update:color="handleColorUpdate"
63
+ >
64
+ <ColorSliderTrack
65
+ class="color-picker-slider-track color-picker-alpha-track"
66
+ >
67
+ <div class="color-picker-slider-track-fill" />
68
+ </ColorSliderTrack>
69
+ <ColorSliderThumb class="color-picker-thumb" />
70
+ </ColorSliderRoot>
71
+
72
+ <!-- Color Fields -->
73
+ <FormInputGroup>
74
+ <ColorFieldRoot
75
+ :model-value="hexColor"
76
+ as-child
77
+ @update:model-value="handleHexUpdate"
78
+ >
79
+ <ColorFieldInput
80
+ class="color-picker-input-hex"
81
+ placeholder="#000000"
82
+ />
83
+ </ColorFieldRoot>
84
+ <ColorFieldRoot
85
+ :model-value="colorObj"
86
+ channel="hue"
87
+ color-space="hsl"
88
+ as-child
89
+ @update:color="handleColorUpdate"
90
+ >
91
+ <ColorFieldInput placeholder="H" />
92
+ </ColorFieldRoot>
93
+ <ColorFieldRoot
94
+ :model-value="colorObj"
95
+ channel="saturation"
96
+ color-space="hsl"
97
+ as-child
98
+ @update:color="handleColorUpdate"
99
+ >
100
+ <ColorFieldInput placeholder="S" />
101
+ </ColorFieldRoot>
102
+ <ColorFieldRoot
103
+ :model-value="colorObj"
104
+ channel="lightness"
105
+ color-space="hsl"
106
+ as-child
107
+ @update:color="handleColorUpdate"
108
+ >
109
+ <ColorFieldInput placeholder="L" />
110
+ </ColorFieldRoot>
111
+ </FormInputGroup>
112
+ </div>
113
+ </Popover>
114
+ </template>
115
+
116
+ <script setup lang="ts">
117
+ import { computed, ref, watch } from 'vue'
118
+ import type { Color } from 'reka-ui'
119
+ import {
120
+ ColorAreaArea,
121
+ ColorAreaRoot,
122
+ ColorAreaThumb,
123
+ ColorFieldInput,
124
+ ColorFieldRoot,
125
+ ColorSliderRoot,
126
+ ColorSliderThumb,
127
+ ColorSliderTrack,
128
+ ColorSwatch,
129
+ colorToString,
130
+ normalizeColor,
131
+ } from 'reka-ui'
132
+ import FormInputGroup from './FormInputGroup.vue'
133
+ import Popover from './Popover.vue'
134
+
135
+ const props = withDefaults(
136
+ defineProps<{
137
+ side?: 'top' | 'right' | 'bottom' | 'left'
138
+ align?: 'start' | 'center' | 'end'
139
+ sideOffset?: number
140
+ alpha?: boolean
141
+ }>(),
142
+ {
143
+ side: 'bottom',
144
+ align: 'start',
145
+ sideOffset: 4,
146
+ },
147
+ )
148
+
149
+ const model = defineModel<string>({ default: '#56d799' })
150
+
151
+ const open = ref(false)
152
+ const colorObj = ref<Color>(normalizeColor(model.value))
153
+ const hexColor = computed(() => colorToString(colorObj.value, 'hex'))
154
+
155
+ watch(hexColor, (val) => {
156
+ model.value = val
157
+ })
158
+
159
+ watch(
160
+ () => model.value,
161
+ (val) => {
162
+ const normalized = normalizeColor(val)
163
+ if (colorToString(normalized, 'hex') !== hexColor.value) {
164
+ colorObj.value = normalized
165
+ }
166
+ },
167
+ )
168
+
169
+ function handleColorUpdate(newColor: Color) {
170
+ colorObj.value = newColor
171
+ }
172
+
173
+ function handleHexUpdate(hex: string) {
174
+ colorObj.value = normalizeColor(hex)
175
+ }
176
+ </script>
177
+
178
+ <style scoped>
179
+ @layer components {
180
+ .color-picker-trigger {
181
+ all: unset;
182
+ display: inline-flex;
183
+ align-items: center;
184
+ gap: var(--size-2);
185
+ padding: var(--ui-padding-block) var(--ui-padding-inline);
186
+ background: var(--button-background);
187
+ border-radius: var(--button-border-radius);
188
+ box-shadow: var(--border-shadow);
189
+ font-family: var(--font-family);
190
+ font-size: var(--ui-font-size);
191
+ cursor: pointer;
192
+ transition:
193
+ box-shadow var(--speed),
194
+ background var(--speed);
195
+ max-width: var(--color-picker-trigger-max-width);
196
+
197
+ &:is(:hover, :focus) {
198
+ box-shadow: var(--border-shadow-highlight);
199
+ }
200
+
201
+ &:focus-visible {
202
+ outline: 2px solid var(--primary);
203
+ outline-offset: 2px;
204
+ }
205
+ }
206
+
207
+ .color-picker-swatch {
208
+ inline-size: var(--size-4);
209
+ block-size: var(--size-4);
210
+ border-radius: var(--border-radius);
211
+ background-color: var(--reka-color-swatch-color);
212
+ box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.15);
213
+ flex-shrink: 0;
214
+ }
215
+
216
+ .color-picker {
217
+ display: grid;
218
+ gap: var(--spacer);
219
+ }
220
+
221
+ .color-picker-area {
222
+ position: relative;
223
+ }
224
+
225
+ .color-picker-area-surface {
226
+ position: relative;
227
+ inline-size: 100%;
228
+ block-size: var(--color-picker-area-height);
229
+ border-radius: var(--border-radius);
230
+ overflow: hidden;
231
+
232
+ &:focus-visible {
233
+ outline: 2px solid var(--primary);
234
+ outline-offset: 2px;
235
+ }
236
+ }
237
+
238
+ .color-picker-thumb {
239
+ all: unset;
240
+ display: block;
241
+ inline-size: var(--color-picker-thumb-size);
242
+ block-size: var(--color-picker-thumb-size);
243
+ border-radius: 50%;
244
+ background: var(--color-picker-thumb-background);
245
+ box-shadow:
246
+ 0 0 0 2px var(--color-picker-thumb-background),
247
+ 0 1px 4px rgb(0 0 0 / 0.3);
248
+ cursor: pointer;
249
+ transition: transform var(--speed);
250
+
251
+ &:is(:hover, :focus) {
252
+ transform: scale(1.1);
253
+ }
254
+
255
+ &:focus-visible {
256
+ outline: 2px solid var(--primary);
257
+ outline-offset: 2px;
258
+ }
259
+ }
260
+
261
+ .color-picker-slider {
262
+ position: relative;
263
+ display: flex;
264
+ align-items: center;
265
+ inline-size: 100%;
266
+ block-size: var(--color-picker-thumb-size);
267
+ }
268
+
269
+ .color-picker-slider-track {
270
+ position: relative;
271
+ flex-grow: 1;
272
+ block-size: var(--color-picker-track-size);
273
+ border-radius: var(--color-picker-track-radius);
274
+ overflow: hidden;
275
+ }
276
+
277
+ .color-picker-slider-track-fill {
278
+ position: absolute;
279
+ inset: 0;
280
+ border-radius: var(--color-picker-track-radius);
281
+ }
282
+
283
+ .color-picker-alpha-track {
284
+ background-image:
285
+ linear-gradient(
286
+ 45deg,
287
+ var(--color-picker-checkerboard) 25%,
288
+ transparent 25%
289
+ ),
290
+ linear-gradient(
291
+ -45deg,
292
+ var(--color-picker-checkerboard) 25%,
293
+ transparent 25%
294
+ ),
295
+ linear-gradient(
296
+ 45deg,
297
+ transparent 75%,
298
+ var(--color-picker-checkerboard) 75%
299
+ ),
300
+ linear-gradient(
301
+ -45deg,
302
+ transparent 75%,
303
+ var(--color-picker-checkerboard) 75%
304
+ );
305
+ background-size: 8px 8px;
306
+ background-position:
307
+ 0 0,
308
+ 0 4px,
309
+ 4px -4px,
310
+ -4px 0;
311
+ }
312
+
313
+ .color-picker :deep(input) {
314
+ text-align: center;
315
+ font-size: var(--font-xs);
316
+ }
317
+ }
318
+ </style>
@@ -17,7 +17,7 @@
17
17
  :disabled="disabled"
18
18
  />
19
19
  <ComboboxTrigger class="combobox-trigger">
20
- <Icon type="chevron-down" />
20
+ <Icon name="chevron-down" />
21
21
  </ComboboxTrigger>
22
22
  </ComboboxAnchor>
23
23
 
@@ -39,7 +39,7 @@
39
39
  >
40
40
  {{ option[labelKey] }}
41
41
  <ComboboxItemIndicator class="combobox-indicator">
42
- <Icon type="check" />
42
+ <Icon name="check" />
43
43
  </ComboboxItemIndicator>
44
44
  </ComboboxItem>
45
45
  </ComboboxViewport>
@@ -25,7 +25,7 @@
25
25
  @pointerdown="open = false"
26
26
  @click="open = false"
27
27
  >
28
- <Icon type="close" />
28
+ <Icon name="close" />
29
29
  </button>
30
30
 
31
31
  <section>
@@ -233,7 +233,7 @@ onBeforeUnmount(() => {
233
233
  }
234
234
 
235
235
  &::backdrop {
236
- background-color: var(--backdrop-background-color);
236
+ background-color: var(--backdrop-background);
237
237
  backdrop-filter: var(--blur);
238
238
  transition:
239
239
  background-color var(--speed) ease,
@@ -257,7 +257,7 @@ onBeforeUnmount(() => {
257
257
  position: fixed;
258
258
  inset: 0;
259
259
  z-index: var(--z-index-overlay);
260
- background-color: var(--backdrop-background-color);
260
+ background-color: var(--backdrop-background);
261
261
  backdrop-filter: var(--blur);
262
262
  transition:
263
263
  background-color var(--speed) ease,
@@ -7,7 +7,7 @@
7
7
  @select="(e: Event) => emit('select', e)"
8
8
  >
9
9
  <DropdownMenuItemIndicator class="dropdown-item-indicator">
10
- <Icon type="check" />
10
+ <Icon name="check" />
11
11
  </DropdownMenuItemIndicator>
12
12
  <slot />
13
13
  </DropdownMenuCheckboxItem>
@@ -7,7 +7,7 @@
7
7
  @select="(e: Event) => emit('select', e)"
8
8
  >
9
9
  <DropdownMenuItemIndicator class="dropdown-item-indicator">
10
- <Icon type="check" />
10
+ <Icon name="check" />
11
11
  </DropdownMenuItemIndicator>
12
12
  <slot />
13
13
  </DropdownMenuRadioItem>
@@ -8,7 +8,7 @@
8
8
  class="form-checkbox-button"
9
9
  >
10
10
  <CheckboxIndicator class="form-checkbox-indicator">
11
- <Icon type="check" />
11
+ <Icon name="check" />
12
12
  </CheckboxIndicator>
13
13
  </CheckboxRoot>
14
14
  <span v-if="$slots.default"><slot /></span>
@@ -46,7 +46,7 @@
46
46
  </DatePickerField>
47
47
 
48
48
  <DatePickerTrigger class="form-date-picker-trigger">
49
- <Icon type="calendar" />
49
+ <Icon name="calendar" />
50
50
  </DatePickerTrigger>
51
51
  </DatePickerAnchor>
52
52
 
@@ -65,11 +65,11 @@
65
65
  >
66
66
  <DatePickerHeader class="form-date-picker-header">
67
67
  <DatePickerPrev class="form-date-picker-nav">
68
- <Icon type="chevron-left" />
68
+ <Icon name="chevron-left" />
69
69
  </DatePickerPrev>
70
70
  <DatePickerHeading class="form-date-picker-heading" />
71
71
  <DatePickerNext class="form-date-picker-nav">
72
- <Icon type="chevron-right" />
72
+ <Icon name="chevron-right" />
73
73
  </DatePickerNext>
74
74
  </DatePickerHeader>
75
75
 
@@ -20,7 +20,6 @@
20
20
  @layer components {
21
21
  .form-item {
22
22
  border-radius: var(--border-radius);
23
- overflow: hidden;
24
23
  display: flex;
25
24
  align-items: center;
26
25
  background: var(--background);
@@ -8,7 +8,7 @@
8
8
  <SelectTrigger class="form-select-trigger">
9
9
  <SelectValue :placeholder="placeholder" />
10
10
  <SelectIcon class="form-select-icon">
11
- <Icon type="chevron-down" />
11
+ <Icon name="chevron-down" />
12
12
  </SelectIcon>
13
13
  </SelectTrigger>
14
14
 
@@ -27,7 +27,7 @@
27
27
  >
28
28
  <SelectItemText>{{ option[labelKey] }}</SelectItemText>
29
29
  <SelectItemIndicator class="form-select-indicator">
30
- <Icon type="check" />
30
+ <Icon name="check" />
31
31
  </SelectItemIndicator>
32
32
  </SelectItem>
33
33
  </SelectViewport>
@@ -11,11 +11,11 @@ import { computed, inject } from 'vue'
11
11
  import { Icon as IconifyIcon } from '@iconify/vue'
12
12
  import { IconAliasesKey, defaultIconAliases } from '../icons'
13
13
 
14
- const props = defineProps<{ type: string }>()
14
+ const props = defineProps<{ name: string }>()
15
15
 
16
16
  const aliases = inject(IconAliasesKey, defaultIconAliases)
17
17
 
18
- const resolvedIcon = computed(() => aliases[props.type] || props.type)
18
+ const resolvedIcon = computed(() => aliases[props.name] || props.name)
19
19
  </script>
20
20
 
21
21
  <style scoped>
@@ -29,7 +29,7 @@
29
29
  class="popover-close tertiary"
30
30
  aria-label="Close"
31
31
  >
32
- <Icon type="close" />
32
+ <Icon name="close" />
33
33
  </PopoverClose>
34
34
 
35
35
  <section>
@@ -7,7 +7,7 @@
7
7
  v-if="dismissable"
8
8
  @click="emit('dismiss')"
9
9
  >
10
- <Icon type="close" />
10
+ <Icon name="close" />
11
11
  </Button>
12
12
  </span>
13
13
  </template>
@@ -25,7 +25,7 @@
25
25
  :as="Button"
26
26
  aria-label="Close"
27
27
  >
28
- <Icon type="close" />
28
+ <Icon name="close" />
29
29
  </ToastClose>
30
30
 
31
31
  <section v-if="toast.description || toast.action || toast.progress">
package/src/base/icons.ts CHANGED
@@ -14,9 +14,10 @@ export const defaultIconAliases: IconAliases = {
14
14
  close: 'lucide:x',
15
15
  copy: 'lucide:copy',
16
16
  edit: 'lucide:pencil',
17
- help: 'lucide:circle-question-mark',
17
+ help: 'lucide:circle-help',
18
18
  home: 'lucide:house',
19
19
  link: 'lucide:link',
20
20
  loader: 'lucide:loader-2',
21
+ menu: 'lucide:menu',
21
22
  wallet: 'lucide:wallet',
22
23
  }
@@ -7,4 +7,5 @@ export const clientOnlyComponents = [
7
7
  'Popover',
8
8
  'Dropdown',
9
9
  'FormDatePicker',
10
+ 'ColorPicker',
10
11
  ]
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ export { default as BottomNav } from './base/components/BottomNav.vue'
6
6
  export { default as Button } from './base/components/Button.vue'
7
7
  export { default as Calendar } from './base/components/Calendar.vue'
8
8
  export { default as Card } from './base/components/Card.vue'
9
+ export { default as ColorPicker } from './base/components/ColorPicker.vue'
9
10
  export { default as Combobox } from './base/components/Combobox.vue'
10
11
  export { default as ConfirmDialog } from './base/components/ConfirmDialog.vue'
11
12
  export { default as CardLink } from './base/components/CardLink.vue'
@@ -30,10 +31,13 @@ export { default as FormItem } from './base/components/FormItem.vue'
30
31
  export { default as FormLabel } from './base/components/FormLabel.vue'
31
32
  export { default as FormRadioGroup } from './base/components/FormRadioGroup.vue'
32
33
  export { default as FormSelect } from './base/components/FormSelect.vue'
34
+ export { default as FormSlider } from './base/components/FormSlider.vue'
35
+ export { default as FormSwitch } from './base/components/FormSwitch.vue'
33
36
  export { default as FormTextarea } from './base/components/FormTextarea.vue'
34
37
  export { default as Icon } from './base/components/Icon.vue'
35
38
  export { default as Loading } from './base/components/Loading.vue'
36
39
  export { default as Opepicon } from './base/components/Opepicon.vue'
40
+ export { default as PinInput } from './base/components/PinInput.vue'
37
41
  export { default as Popover } from './base/components/Popover.vue'
38
42
  export { default as Progress } from './base/components/Progress.vue'
39
43
  export { default as Prose } from './base/components/Prose.vue'