@1001-digital/components 1.3.0 → 1.5.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,7 +1,8 @@
1
1
  {
2
2
  "name": "@1001-digital/components",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
+ "main": "./src/index.ts",
5
6
  "sideEffects": [
6
7
  "*.css"
7
8
  ],
@@ -14,18 +15,18 @@
14
15
  ],
15
16
  "peerDependencies": {
16
17
  "vue": "^3.5.0",
17
- "@1001-digital/styles": "^1.1.0"
18
+ "@1001-digital/styles": "^1.3.0"
18
19
  },
19
20
  "dependencies": {
20
21
  "@iconify/vue": "^5.0.0",
21
- "@internationalized/date": "^3.8.0",
22
- "@types/luxon": "^3.7.0",
22
+ "@internationalized/date": "^3.12.0",
23
23
  "@visualizevalue/opepicons": "^0.1.0",
24
- "@vueuse/core": "^14.2.0",
24
+ "@vueuse/core": "^14.2.1",
25
25
  "luxon": "^3.7.0",
26
- "reka-ui": "^2.8.0"
26
+ "reka-ui": "^2.9.0"
27
27
  },
28
28
  "devDependencies": {
29
- "vue": "^3.5.0"
29
+ "@types/luxon": "^3.7.0",
30
+ "vue": "^3.5.30"
30
31
  }
31
32
  }
@@ -14,10 +14,14 @@
14
14
  flex-wrap: wrap;
15
15
  gap: var(--spacer-sm);
16
16
 
17
- &:not(.left) {
17
+ &:not(.left):not(.center) {
18
18
  justify-content: flex-end;
19
19
  }
20
20
 
21
+ &.center {
22
+ justify-content: center;
23
+ }
24
+
21
25
  &:empty {
22
26
  display: none !important;
23
27
  }
@@ -39,21 +39,27 @@ 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
+
42
48
  .app-shell {
43
49
  display: flex;
44
- min-block-size: var(--100vh);
50
+ block-size: 100dvh;
51
+ overflow: hidden;
45
52
  }
46
53
 
47
54
  .app-shell-main {
48
55
  flex: 1;
49
56
  min-inline-size: 0;
50
- }
51
-
52
- .app-shell:has(.bottom-nav) .app-shell-main {
53
- padding-block-end: var(--bottom-nav-height);
57
+ overflow-y: auto;
58
+ overscroll-behavior-y: contain;
59
+ padding-block-start: env(safe-area-inset-top);
54
60
 
55
- @media (min-width: 1024px) {
56
- padding-block-end: 0;
61
+ &:has(+ nav.bottom-nav) {
62
+ padding-block-end: var(--bottom-nav-height);
57
63
  }
58
64
  }
59
65
  }
@@ -1,6 +1,8 @@
1
1
  <template>
2
2
  <nav class="bottom-nav">
3
- <slot />
3
+ <div class="bottom-nav-items">
4
+ <slot />
5
+ </div>
4
6
  </nav>
5
7
  </template>
6
8
 
@@ -17,12 +19,16 @@
17
19
  border-block-start: var(--border);
18
20
  display: flex;
19
21
  align-items: center;
20
- justify-content: space-evenly;
22
+ justify-content: center;
21
23
  padding-block-end: env(safe-area-inset-bottom);
24
+ }
22
25
 
23
- @media (min-width: 1024px) {
24
- display: none;
25
- }
26
+ .bottom-nav-items {
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: space-evenly;
30
+ inline-size: 100%;
31
+ max-inline-size: var(--bottom-nav-max-inline-size);
26
32
 
27
33
  > a,
28
34
  > button {
@@ -2,6 +2,7 @@
2
2
  <Teleport :to="teleportTarget || 'body'">
3
3
  <Transition
4
4
  :css="false"
5
+ appear
5
6
  @enter="onEnter"
6
7
  @leave="onLeave"
7
8
  @after-leave="() => emit('closed')"
@@ -15,24 +16,26 @@
15
16
  @cancel.stop.prevent="closable && (open = false)"
16
17
  @click="onDialogClick"
17
18
  >
18
- <h1 v-if="title">{{ title }}</h1>
19
- <button
20
- v-if="closable"
21
- class="close"
22
- :title="`Close ${title || 'Dialog'}`"
23
- @pointerdown="open = false"
24
- @click="open = false"
25
- >
26
- <Icon type="close" />
27
- </button>
28
-
29
- <section>
30
- <slot />
31
- </section>
32
-
33
- <footer v-if="$slots.footer">
34
- <slot name="footer" />
35
- </footer>
19
+ <div class="dialog-content">
20
+ <h1 v-if="title">{{ title }}</h1>
21
+ <button
22
+ v-if="closable"
23
+ class="close"
24
+ :title="`Close ${title || 'Dialog'}`"
25
+ @pointerdown="open = false"
26
+ @click="open = false"
27
+ >
28
+ <Icon type="close" />
29
+ </button>
30
+
31
+ <section>
32
+ <slot />
33
+ </section>
34
+
35
+ <footer v-if="$slots.footer">
36
+ <slot name="footer" />
37
+ </footer>
38
+ </div>
36
39
  </component>
37
40
  </Transition>
38
41
 
@@ -144,14 +147,71 @@ onBeforeUnmount(() => {
144
147
  background: var(--background);
145
148
  color: var(--color);
146
149
  border: var(--border);
147
- border-radius: var(--border-radius);
150
+ border-radius: var(--dialog-border-radius);
148
151
  padding: 0;
149
- max-block-size: 80dvh;
150
- container-type: inline-size;
151
- display: grid;
152
- grid-template-rows: auto 1fr auto;
153
152
  overflow: hidden;
154
153
 
154
+ > .dialog-content {
155
+ display: grid;
156
+ grid-template-rows: auto 1fr auto;
157
+ max-block-size: 80dvh;
158
+
159
+ > h1:first-child,
160
+ > .close {
161
+ display: flex;
162
+ align-items: center;
163
+ block-size: calc(var(--spacer) * 2);
164
+ box-shadow: var(--border-shadow);
165
+ padding-inline-start: var(--spacer);
166
+ font-family: var(--font-family);
167
+ font-size: var(--ui-font-size);
168
+ text-transform: var(--ui-text-transform);
169
+ margin: 0;
170
+ }
171
+
172
+ > h1:first-child {
173
+ padding-right: calc(var(--spacer) * 3);
174
+ }
175
+
176
+ > .close {
177
+ position: absolute;
178
+ top: 0;
179
+ right: 0;
180
+ inline-size: calc(var(--spacer) * 2);
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ padding: 0;
185
+ border-radius: 0;
186
+ border-start-end-radius: var(--dialog-border-radius);
187
+
188
+ &:is(:hover, :active, :focus, .active) {
189
+ outline: none;
190
+ }
191
+ }
192
+
193
+ > section {
194
+ overflow-y: auto;
195
+ overscroll-behavior: contain;
196
+ padding: var(--spacer);
197
+ display: grid;
198
+ gap: var(--spacer);
199
+ }
200
+
201
+ > footer {
202
+ display: flex;
203
+ gap: var(--spacer);
204
+ justify-content: safe flex-end;
205
+ padding: var(--spacer);
206
+ border-block-start: var(--border);
207
+ overflow-x: auto;
208
+
209
+ &:empty {
210
+ display: none;
211
+ }
212
+ }
213
+ }
214
+
155
215
  /* Entry/exit animations */
156
216
  opacity: 1;
157
217
  scale: 1;
@@ -213,61 +273,6 @@ onBeforeUnmount(() => {
213
273
  outline: none;
214
274
  }
215
275
 
216
- > h1:first-child,
217
- > .close {
218
- display: flex;
219
- align-items: center;
220
- block-size: calc(var(--spacer) * 2);
221
- box-shadow: var(--border-shadow);
222
- padding-inline-start: var(--spacer);
223
- font-family: var(--font-family);
224
- font-size: var(--ui-font-size);
225
- text-transform: var(--ui-text-transform);
226
- margin: 0;
227
- }
228
-
229
- > h1:first-child {
230
- padding-right: calc(var(--spacer) * 3);
231
- }
232
-
233
- > .close {
234
- position: absolute;
235
- top: 0;
236
- right: 0;
237
- inline-size: calc(var(--spacer) * 2);
238
- display: flex;
239
- align-items: center;
240
- justify-content: center;
241
- padding: 0;
242
- border-radius: 0;
243
- border-start-end-radius: var(--border-radius);
244
-
245
- &:is(:hover, :active, :focus, .active) {
246
- outline: none;
247
- }
248
- }
249
-
250
- > section {
251
- overflow-y: auto;
252
- overscroll-behavior: contain;
253
- padding: var(--spacer);
254
- display: grid;
255
- gap: var(--spacer);
256
- }
257
-
258
- > footer {
259
- display: flex;
260
- gap: var(--spacer);
261
- justify-content: safe flex-end;
262
- padding: var(--spacer);
263
- border-block-start: var(--border);
264
- overflow-x: auto;
265
-
266
- &:empty {
267
- display: none;
268
- }
269
- }
270
-
271
276
  &.large {
272
277
  --dialog-width: min(90vw, 64rem);
273
278
  }
@@ -20,6 +20,7 @@
20
20
  @layer components {
21
21
  .form-item {
22
22
  border-radius: var(--border-radius);
23
+ overflow: hidden;
23
24
  display: flex;
24
25
  align-items: center;
25
26
  background: var(--background);
@@ -65,24 +66,14 @@
65
66
  border-end-end-radius: var(--border-radius);
66
67
  }
67
68
 
68
- &:has(> .prefix) {
69
+ &:has(> .prefix) :deep(> :last-child) {
69
70
  border-start-start-radius: 0;
70
71
  border-end-start-radius: 0;
71
-
72
- & :deep(> :last-child) {
73
- border-start-start-radius: 0;
74
- border-end-start-radius: 0;
75
- }
76
72
  }
77
73
 
78
- &:has(> .suffix) {
74
+ &:has(> .suffix) :deep(> :first-child) {
79
75
  border-start-end-radius: 0;
80
76
  border-end-end-radius: 0;
81
-
82
- & :deep(> :first-child) {
83
- border-start-end-radius: 0;
84
- border-end-end-radius: 0;
85
- }
86
77
  }
87
78
  }
88
79
  }
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <div
3
+ class="prose"
4
+ :class="{ centered }"
5
+ >
6
+ <slot />
7
+ </div>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ defineProps<{
12
+ centered?: boolean
13
+ }>()
14
+ </script>
@@ -82,6 +82,7 @@ onMounted(() => {
82
82
  if (isLargeScreen.value) return
83
83
 
84
84
  const touch = e.touches[0]
85
+ if (!touch) return
85
86
  startX = touch.clientX
86
87
  startY = touch.clientY
87
88
  tracking = false
@@ -103,6 +104,7 @@ onMounted(() => {
103
104
  if (!tracking || isLargeScreen.value) return
104
105
 
105
106
  const touch = e.touches[0]
107
+ if (!touch) return
106
108
  const dx = touch.clientX - startX
107
109
  const dy = touch.clientY - startY
108
110
 
@@ -66,10 +66,7 @@
66
66
  </section>
67
67
  </ToastRoot>
68
68
 
69
- <ToastViewport
70
- class="toast-viewport"
71
- :class="[position]"
72
- />
69
+ <ToastViewport class="toast-viewport" />
73
70
  </ToastProvider>
74
71
 
75
72
  </template>
@@ -94,12 +91,10 @@ withDefaults(
94
91
  defineProps<{
95
92
  duration?: number
96
93
  swipeDirection?: 'right' | 'left' | 'up' | 'down'
97
- position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
98
94
  }>(),
99
95
  {
100
96
  duration: 5_000,
101
97
  swipeDirection: 'right',
102
- position: 'bottom-right',
103
98
  },
104
99
  )
105
100
 
@@ -114,6 +109,7 @@ const onClose = (id: string) => {
114
109
  @layer components {
115
110
  :deep(.toast-viewport) {
116
111
  position: fixed;
112
+ inset: var(--toast-inset);
117
113
  z-index: var(--z-index-toast);
118
114
  display: flex;
119
115
  flex-direction: column;
@@ -123,26 +119,6 @@ const onClose = (id: string) => {
123
119
  list-style: none;
124
120
  max-width: 100vw;
125
121
  outline: none;
126
-
127
- &.bottom-right {
128
- bottom: 0;
129
- right: 0;
130
- }
131
-
132
- &.bottom-left {
133
- bottom: 0;
134
- left: 0;
135
- }
136
-
137
- &.top-right {
138
- top: 0;
139
- right: 0;
140
- }
141
-
142
- &.top-left {
143
- top: 0;
144
- left: 0;
145
- }
146
122
  }
147
123
 
148
124
  :deep(.toast) {
@@ -153,7 +129,7 @@ const onClose = (id: string) => {
153
129
  max-inline-size: calc(100vw - var(--spacer) * 2);
154
130
  padding: 0;
155
131
  border: var(--border);
156
- border-radius: var(--border-radius);
132
+ border-radius: var(--toast-border-radius);
157
133
  overflow: hidden;
158
134
  font-family: var(--font-family);
159
135
  font-size: var(--ui-font-size);
@@ -272,7 +248,7 @@ const onClose = (id: string) => {
272
248
  right: 0;
273
249
  box-shadow: var(--border-shadow) !important;
274
250
  border-radius: 0 !important;
275
- border-start-end-radius: var(--border-radius) !important;
251
+ border-start-end-radius: var(--toast-border-radius) !important;
276
252
  }
277
253
 
278
254
  .actions {
@@ -0,0 +1,10 @@
1
+ // Components that require browser APIs and must be rendered client-only
2
+ export const clientOnlyComponents = [
3
+ 'Combobox',
4
+ 'ConfirmDialog',
5
+ 'Dialog',
6
+ 'Toasts',
7
+ 'Popover',
8
+ 'Dropdown',
9
+ 'FormDatePicker',
10
+ ]
package/src/index.ts CHANGED
@@ -36,6 +36,7 @@ export { default as Loading } from './base/components/Loading.vue'
36
36
  export { default as Opepicon } from './base/components/Opepicon.vue'
37
37
  export { default as Popover } from './base/components/Popover.vue'
38
38
  export { default as Progress } from './base/components/Progress.vue'
39
+ export { default as Prose } from './base/components/Prose.vue'
39
40
  export { default as Sidebar } from './base/components/Sidebar.vue'
40
41
  export { default as Tag } from './base/components/Tag.vue'
41
42
  export { default as Tags } from './base/components/Tags.vue'
@@ -84,3 +85,5 @@ export type { DateValue } from '@internationalized/date'
84
85
  export { IconAliasesKey, defaultIconAliases } from './base/icons'
85
86
  export type { IconAliases } from './base/icons'
86
87
  export { LinkComponentKey } from './base/link'
88
+
89
+ export { clientOnlyComponents } from './client-only'