daisy-ui-kit 5.0.12 → 5.1.2

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/README.md CHANGED
@@ -14,7 +14,7 @@ Import components directly from the package:
14
14
 
15
15
  ```vue
16
16
  <script setup lang="ts">
17
- import { Button, Badge } from 'daisy-ui-kit'
17
+ import { Badge, Button } from 'daisy-ui-kit'
18
18
  </script>
19
19
 
20
20
  <template>
@@ -1,8 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  const props = defineProps<{
3
- orientation: string
4
- horizontal: boolean
5
- vertical: boolean
3
+ orientation?: 'horizontal' | 'vertical'
4
+ horizontal?: boolean
5
+ vertical?: boolean
6
6
  }>()
7
7
  </script>
8
8
 
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -53,7 +54,7 @@ export default defineComponent({
53
54
  },
54
55
  ])
55
56
 
56
- return () => h(props.is as any, mergeProps(attrs, { class: classes.value }), slots.default?.())
57
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: classes.value }), slots.default?.())
57
58
  },
58
59
  })
59
60
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -103,7 +104,7 @@ export default defineComponent({
103
104
  }
104
105
 
105
106
  return () => {
106
- const tag = props.is || 'button'
107
+ const tag = props.is ? resolveIs(props.is) : 'button'
107
108
  const isBtnEl = isButton.value
108
109
 
109
110
  return h(
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -32,7 +33,7 @@ export default defineComponent({
32
33
  },
33
34
  ])
34
35
 
35
- return () => h(props.is as any, mergeProps(attrs, { class: classes.value }), slots.default?.())
36
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: classes.value }), slots.default?.())
36
37
  },
37
38
  })
38
39
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -7,7 +8,7 @@ export default defineComponent({
7
8
  is: { type: [String, Object], default: 'span' },
8
9
  },
9
10
  setup(props, { slots, attrs }) {
10
- return () => h(props.is as any, mergeProps(attrs, { class: 'countdown' }), slots.default?.())
11
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: 'countdown' }), slots.default?.())
11
12
  },
12
13
  })
13
14
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -33,7 +34,7 @@ export default defineComponent({
33
34
  },
34
35
  ])
35
36
 
36
- return () => h(props.is as any, mergeProps(attrs, { class: classes.value }), slots.default?.())
37
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: classes.value }), slots.default?.())
37
38
  },
38
39
  })
39
40
  </script>
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
- import { useId } from 'vue'
3
2
  import { useElementHover } from '@vueuse/core'
4
- import { onMounted, provide, ref, watch } from 'vue'
3
+ import { onMounted, provide, ref, useId, watch } from 'vue'
5
4
 
6
5
  const props = withDefaults(
7
6
  defineProps<{
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -9,10 +10,11 @@ export default defineComponent({
9
10
  },
10
11
  setup(props, { slots, attrs }) {
11
12
  return () =>
12
- h(props.is as any, mergeProps(attrs, { class: 'fieldset bg-base-200 border-base-300 rounded-box border p-4' }), [
13
- props.legend ? h('legend', { class: 'fieldset-legend' }, props.legend) : slots.legend?.(),
14
- slots.default?.(),
15
- ])
13
+ h(
14
+ resolveIs(props.is),
15
+ mergeProps(attrs, { class: 'fieldset bg-base-200 border-base-300 rounded-box border p-4' }),
16
+ [props.legend ? h('legend', { class: 'fieldset-legend' }, props.legend) : slots.legend?.(), slots.default?.()],
17
+ )
16
18
  },
17
19
  })
18
20
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -81,7 +82,7 @@ export default defineComponent({
81
82
  },
82
83
  ])
83
84
 
84
- return () => h(props.is as any, mergeProps(attrs, { class: classes.value }), slots.default?.())
85
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: classes.value }), slots.default?.())
85
86
  },
86
87
  })
87
88
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -51,7 +52,7 @@ export default defineComponent({
51
52
  },
52
53
  ])
53
54
 
54
- return () => h(props.is as any, mergeProps(attrs, { class: classes.value }), slots.default?.())
55
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: classes.value }), slots.default?.())
55
56
  },
56
57
  })
57
58
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -7,7 +8,7 @@ export default defineComponent({
7
8
  is: { type: [String, Object], default: 'div' },
8
9
  },
9
10
  setup(props, { slots, attrs }) {
10
- return () => h(props.is as any, mergeProps(attrs, { class: 'indicator' }), slots.default?.())
11
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: 'indicator' }), slots.default?.())
11
12
  },
12
13
  })
13
14
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -30,7 +31,7 @@ export default defineComponent({
30
31
  },
31
32
  ])
32
33
 
33
- return () => h(props.is as any, mergeProps(attrs, { class: classes.value }), slots.default?.())
34
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: classes.value }), slots.default?.())
34
35
  },
35
36
  })
36
37
  </script>
@@ -1,5 +1,19 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ direction?: 'horizontal' | 'vertical'
4
+ horizontal?: boolean
5
+ vertical?: boolean
6
+ }>()
7
+ </script>
8
+
1
9
  <template>
2
- <div class="join">
10
+ <div
11
+ class="join"
12
+ :class="{
13
+ 'join-vertical': direction === 'vertical' || vertical,
14
+ 'join-horizontal': direction === 'horizontal' || horizontal,
15
+ }"
16
+ >
3
17
  <slot />
4
18
  </div>
5
19
  </template>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -8,7 +9,8 @@ export default defineComponent({
8
9
  glass: { type: Boolean, default: false },
9
10
  },
10
11
  setup(props, { slots, attrs }) {
11
- return () => h(props.is as any, mergeProps(attrs, { class: ['navbar', { glass: props.glass }] }), slots.default?.())
12
+ return () =>
13
+ h(resolveIs(props.is), mergeProps(attrs, { class: ['navbar', { glass: props.glass }] }), slots.default?.())
12
14
  },
13
15
  })
14
16
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -7,7 +8,7 @@ export default defineComponent({
7
8
  is: { type: [String, Object], default: 'div' },
8
9
  },
9
10
  setup(props, { slots, attrs }) {
10
- return () => h(props.is as any, mergeProps(attrs, { class: 'navbar-center' }), slots.default?.())
11
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: 'navbar-center' }), slots.default?.())
11
12
  },
12
13
  })
13
14
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -7,7 +8,7 @@ export default defineComponent({
7
8
  is: { type: [String, Object], default: 'div' },
8
9
  },
9
10
  setup(props, { slots, attrs }) {
10
- return () => h(props.is as any, mergeProps(attrs, { class: 'navbar-end' }), slots.default?.())
11
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: 'navbar-end' }), slots.default?.())
11
12
  },
12
13
  })
13
14
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -7,7 +8,7 @@ export default defineComponent({
7
8
  is: { type: [String, Object], default: 'div' },
8
9
  },
9
10
  setup(props, { slots, attrs }) {
10
- return () => h(props.is as any, mergeProps(attrs, { class: 'navbar-start' }), slots.default?.())
11
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: 'navbar-start' }), slots.default?.())
11
12
  },
12
13
  })
13
14
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -7,7 +8,7 @@ export default defineComponent({
7
8
  is: { type: [String, Object], default: 'span' },
8
9
  },
9
10
  setup(props, { slots, attrs }) {
10
- return () => h(props.is as any, mergeProps(attrs, { class: 'skeleton skeleton-text' }), slots.default?.())
11
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: 'skeleton skeleton-text' }), slots.default?.())
11
12
  },
12
13
  })
13
14
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -22,7 +23,7 @@ export default defineComponent({
22
23
  },
23
24
  ])
24
25
 
25
- return () => h(props.is as any, mergeProps(attrs, { class: classes.value }), slots.default?.())
26
+ return () => h(resolveIs(props.is), mergeProps(attrs, { class: classes.value }), slots.default?.())
26
27
  },
27
28
  })
28
29
  </script>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { computed, defineComponent, h, mergeProps } from 'vue'
3
+ import { resolveIs } from '../utils/resolve-is'
3
4
 
4
5
  export default defineComponent({
5
6
  inheritAttrs: false,
@@ -170,7 +171,7 @@ export default defineComponent({
170
171
 
171
172
  return () =>
172
173
  h(
173
- props.is as any,
174
+ resolveIs(props.is),
174
175
  mergeProps(attrs, { ...(props.label ? { 'data-role': 'label' } : {}), class: classes.value }),
175
176
  slots.default?.(),
176
177
  )
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
- import { useId } from 'vue'
3
2
  import { useElementHover } from '@vueuse/core'
4
- import { computed, onMounted, provide, ref, watch } from 'vue'
3
+ import { computed, onMounted, provide, ref, useId, watch } from 'vue'
5
4
 
6
5
  const props = withDefaults(
7
6
  defineProps<{
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
- import Button from '../Button.vue'
3
2
  import { useClipboard } from '@vueuse/core'
3
+ import Button from '../Button.vue'
4
4
 
5
5
  const props = defineProps({
6
6
  code: {
@@ -4,6 +4,7 @@ import { useFuse } from '@vueuse/integrations/useFuse'
4
4
  import { computed, nextTick, ref, watch } from 'vue'
5
5
 
6
6
  const { isSearchOpen, openSearch, closeSearch } = useSearch()
7
+ const { themes, setTheme } = useDaisyTheme()
7
8
 
8
9
  // Handle escape key
9
10
  onKeyStroke('Escape', () => {
@@ -25,7 +26,19 @@ const search = ref('')
25
26
  const searchInput = ref<HTMLInputElement | null>(null)
26
27
  const { allLinks } = useNav()
27
28
 
28
- const tags = allLinks.flatMap(item => item.tags)
29
+ // Build theme search items
30
+ const themeItems = themes.value
31
+ .filter(t => t.theme !== 'system')
32
+ .map(t => ({
33
+ label: t.theme,
34
+ to: '',
35
+ tags: ['theme'],
36
+ isTheme: true,
37
+ }))
38
+
39
+ const allSearchItems = [...allLinks, ...themeItems]
40
+
41
+ const tags = allSearchItems.flatMap(item => item.tags)
29
42
  const matchingTag = computed(() => {
30
43
  if (search.value.length < 2) {
31
44
  return null
@@ -34,11 +47,22 @@ const matchingTag = computed(() => {
34
47
  })
35
48
 
36
49
  // search results and popular results
37
- const { results } = useFuse(search, allLinks, {
50
+ const { results } = useFuse(search, allSearchItems, {
38
51
  fuseOptions: { keys: ['label', 'tags'], includeScore: true, distance: 3 },
39
52
  resultLimit: 12,
40
53
  })
41
54
 
55
+ // Split results into nav links and themes
56
+ const navResults = computed(() => results.value.filter(r => !(r.item as any).isTheme))
57
+ const themeResults = computed(() => {
58
+ const fromFuse = results.value.filter(r => (r.item as any).isTheme)
59
+ // If user typed "theme", show all themes (fuse's resultLimit caps at 12)
60
+ if (fromFuse.length > 0 && matchingTag.value === 'theme') {
61
+ return themeItems.map(item => ({ item }))
62
+ }
63
+ return fromFuse
64
+ })
65
+
42
66
  const popularResults = ['Button', 'Menu', 'Drawer', 'Tabs', 'Dropdown']
43
67
  .map(label => allLinks.find(item => item.label === label)!)
44
68
  .filter(Boolean)
@@ -56,15 +80,24 @@ const eitherResults = computed(() => {
56
80
  if (results.value.length === 0) {
57
81
  return allDefaultResults.value
58
82
  }
59
- return results.value
83
+ return [...navResults.value, ...themeResults.value]
60
84
  })
61
85
 
62
86
  // track the highlighted index in the list
63
87
  const highlightedIndex = ref(0)
88
+ const resultsContainer = ref<HTMLElement | null>(null)
64
89
  const highlightedItem = computed(() => {
65
90
  return eitherResults.value[highlightedIndex.value]?.item
66
91
  })
67
92
 
93
+ // scroll highlighted item into view
94
+ watch(highlightedIndex, () => {
95
+ nextTick(() => {
96
+ const el = resultsContainer.value?.querySelector('[data-highlighted]')
97
+ el?.scrollIntoView({ block: 'nearest' })
98
+ })
99
+ })
100
+
68
101
  // when results change, reset the highlighted index
69
102
  watch(eitherResults, () => {
70
103
  highlightedIndex.value = 0
@@ -82,14 +115,23 @@ watch(isSearchOpen, val => {
82
115
  }
83
116
  })
84
117
 
85
- // enter --> navigate to highlighted item
118
+ // enter --> navigate to highlighted item or apply theme
86
119
  function handleEnter() {
87
120
  if (highlightedItem.value) {
88
- navigateTo(highlightedItem.value.to)
121
+ if ((highlightedItem.value as any).isTheme) {
122
+ setTheme(highlightedItem.value.label)
123
+ } else {
124
+ navigateTo(highlightedItem.value.to)
125
+ }
89
126
  closeSearch()
90
127
  }
91
128
  }
92
129
 
130
+ function handleThemeClick(themeName: string) {
131
+ setTheme(themeName)
132
+ closeSearch()
133
+ }
134
+
93
135
  // arrow up --> highlighted previous item
94
136
  function handleArrowUp() {
95
137
  highlightedIndex.value = Math.max(highlightedIndex.value - 1, 0)
@@ -128,7 +170,7 @@ function handleResultClick(to: string) {
128
170
  </div>
129
171
 
130
172
  <!-- Results -->
131
- <div class="max-h-[60vh] overflow-y-auto">
173
+ <div ref="resultsContainer" class="max-h-[60vh] overflow-y-auto">
132
174
  <div v-if="!search.length" class="p-2">
133
175
  <Text sm class="px-3 py-2 opacity-50 uppercase tracking-wider">Popular</Text>
134
176
  <Menu class="w-full">
@@ -136,6 +178,7 @@ function handleResultClick(to: string) {
136
178
  v-for="(result, index) in popularResults"
137
179
  :key="result.item.label"
138
180
  :class="{ 'bg-primary/10': index === highlightedIndex }"
181
+ :data-highlighted="index === highlightedIndex ? '' : undefined"
139
182
  >
140
183
  <a class="flex items-center gap-3" @click="handleResultClick(result.item.to)">
141
184
  <Icon
@@ -154,6 +197,7 @@ function handleResultClick(to: string) {
154
197
  v-for="(result, index) in newResults"
155
198
  :key="result.item.label"
156
199
  :class="{ 'bg-primary/10': index + popularResults.length === highlightedIndex }"
200
+ :data-highlighted="index + popularResults.length === highlightedIndex ? '' : undefined"
157
201
  >
158
202
  <a class="flex items-center gap-3" @click="handleResultClick(result.item.to)">
159
203
  <Icon
@@ -169,26 +213,53 @@ function handleResultClick(to: string) {
169
213
  </div>
170
214
 
171
215
  <div v-else-if="results.length" class="p-2">
172
- <Text sm class="px-3 py-2 opacity-50 uppercase tracking-wider">Results</Text>
173
- <Menu class="w-full">
174
- <MenuItem
175
- v-for="(result, index) in results"
176
- :key="result.item.label"
177
- :class="{ 'bg-primary/10': index === highlightedIndex }"
178
- >
179
- <a class="flex items-center gap-3" @click="handleResultClick(result.item.to)">
180
- <Icon
181
- v-if="(result.item as any).icon"
182
- :name="(result.item as any).icon"
183
- class="size-5 opacity-60"
184
- />
185
- <span class="flex-1">{{ result.item.label }}</span>
186
- <Badge v-if="matchingTag && result.item.tags.includes(matchingTag)" warning sm>
187
- {{ matchingTag }}
188
- </Badge>
189
- </a>
190
- </MenuItem>
191
- </Menu>
216
+ <template v-if="navResults.length">
217
+ <Text sm class="px-3 py-2 opacity-50 uppercase tracking-wider">Results</Text>
218
+ <Menu class="w-full">
219
+ <MenuItem
220
+ v-for="(result, index) in navResults"
221
+ :key="result.item.label"
222
+ :class="{ 'bg-primary/10': index === highlightedIndex }"
223
+ :data-highlighted="index === highlightedIndex ? '' : undefined"
224
+ >
225
+ <a class="flex items-center gap-3" @click="handleResultClick(result.item.to)">
226
+ <Icon
227
+ v-if="(result.item as any).icon"
228
+ :name="(result.item as any).icon"
229
+ class="size-5 opacity-60"
230
+ />
231
+ <span class="flex-1">{{ result.item.label }}</span>
232
+ <Badge v-if="matchingTag && result.item.tags.includes(matchingTag)" warning sm>
233
+ {{ matchingTag }}
234
+ </Badge>
235
+ </a>
236
+ </MenuItem>
237
+ </Menu>
238
+ </template>
239
+
240
+ <template v-if="themeResults.length">
241
+ <Text sm class="px-3 py-2 opacity-50 uppercase tracking-wider" :class="{ 'mt-4': navResults.length }">
242
+ Themes
243
+ </Text>
244
+ <Menu class="w-full">
245
+ <li
246
+ v-for="(result, index) in themeResults"
247
+ :key="result.item.label"
248
+ :data-theme="result.item.label"
249
+ :data-highlighted="index + navResults.length === highlightedIndex ? '' : undefined"
250
+ >
251
+ <a
252
+ class="flex items-center gap-3"
253
+ :style="{ backgroundColor: 'var(--color-base-100)', color: 'var(--color-base-content)' }"
254
+ :class="{ 'bg-primary! text-primary-content!': index + navResults.length === highlightedIndex }"
255
+ @click="handleThemeClick(result.item.label)"
256
+ >
257
+ <ThemeTile :theme="result.item.label" xs class="size-5!" />
258
+ <span class="flex-1">{{ result.item.label }}</span>
259
+ </a>
260
+ </li>
261
+ </Menu>
262
+ </template>
192
263
  </div>
193
264
 
194
265
  <div v-else class="p-8 text-center">
@@ -56,7 +56,7 @@ function setupIntersectionObserver() {
56
56
  },
57
57
  )
58
58
 
59
- // Observe all headings
59
+ // Observe all headings (ids are auto-generated by scanHeadings if missing)
60
60
  const headings = document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]')
61
61
  headings.forEach(heading => {
62
62
  headingObserver?.observe(heading)
@@ -90,9 +90,10 @@ function scanHeadings() {
90
90
  return
91
91
  }
92
92
 
93
- // Find all headings (h1-h6) with IDs
94
- const headings = document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]')
93
+ // Find all headings (h1-h6), auto-generating ids for any that lack one
94
+ const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6')
95
95
  const links: TocLink[] = []
96
+ const usedIds = new Set<string>()
96
97
 
97
98
  // Get the page title from the first h1
98
99
  const h1 = document.querySelector('h1')
@@ -107,6 +108,25 @@ function scanHeadings() {
107
108
  return
108
109
  }
109
110
 
111
+ // Auto-generate id from text content if missing
112
+ if (!heading.id) {
113
+ const text = heading.textContent || ''
114
+ const slug = text
115
+ .toLowerCase()
116
+ .trim()
117
+ .replace(/[^\w\s-]/g, '')
118
+ .replace(/[\s_]+/g, '-')
119
+ .replace(/^-+|-+$/g, '')
120
+ // Deduplicate
121
+ let candidate = slug
122
+ let n = 1
123
+ while (usedIds.has(candidate)) {
124
+ candidate = `${slug}-${n++}`
125
+ }
126
+ heading.id = candidate
127
+ }
128
+ usedIds.add(heading.id)
129
+
110
130
  const id = heading.id
111
131
  const level = Number.parseInt(heading.tagName.substring(1), 10)
112
132
 
@@ -17,6 +17,20 @@ export interface CalendarOptions {
17
17
  weekdaysShort?: string[]
18
18
  /** Full weekday names */
19
19
  weekdays?: string[]
20
+ /** Disable weekend days */
21
+ disableWeekends?: boolean
22
+ /** Dates that have events (highlighted) */
23
+ events?: string[]
24
+ /** Number of months to display side by side */
25
+ numberOfMonths?: number
26
+ /** Right-to-left layout */
27
+ isRTL?: boolean
28
+ /** Year range for the year selector [start, end] */
29
+ yearRange?: [number, number]
30
+ /** Date format string */
31
+ format?: string
32
+ /** Custom date-to-string formatter */
33
+ toString?: (date: Date, format: string) => string
20
34
  }
21
35
 
22
36
  export interface CalendarDay {
@@ -24,13 +24,29 @@ function normalizeTheme(input: DaisyThemeInput): DaisyThemeMeta {
24
24
  return { ...input }
25
25
  }
26
26
 
27
- // Simple reactive state - storage parameter handles persistence if needed
28
- function useSSRState<T>(_key: string, init: () => T): Ref<T> {
29
- return ref(init()) as Ref<T>
27
+ // Shared state factory uses Nuxt useState when available, falls back to
28
+ // module-level refs for standalone Vue usage. Nuxt's useState ensures
29
+ // SSR-to-client hydration and per-request isolation on the server.
30
+ const sharedRefs = new Map<string, Ref<any>>()
31
+ function useSharedState<T>(key: string, init: () => T): Ref<T> {
32
+ // Try Nuxt's useState (auto-imported in Nuxt context)
33
+ if (typeof useState === 'function') {
34
+ try {
35
+ return (useState as any)(key, init) as Ref<T>
36
+ } catch {
37
+ // Not in Nuxt runtime — fall through to ref-based approach
38
+ }
39
+ }
40
+ // Fallback for standalone Vue: module-level shared refs
41
+ if (!sharedRefs.has(key)) {
42
+ sharedRefs.set(key, ref(init()) as Ref<T>)
43
+ }
44
+ return sharedRefs.get(key) as Ref<T>
30
45
  }
31
46
 
32
- // Global storage ref - set once in app.vue, reused elsewhere
33
- let globalStorageRef: Ref<string> | null = null
47
+ // Holds the canonical theme ref (cookie-backed or shared state)
48
+ // so all callers of useDaisyTheme() read/write the same ref.
49
+ let themeRef: Ref<string> | null = null
34
50
 
35
51
  /**
36
52
  * useDaisyTheme composable
@@ -41,27 +57,26 @@ let globalStorageRef: Ref<string> | null = null
41
57
  * Calling with no arguments (in any component): reuses global state.
42
58
  */
43
59
  export function useDaisyTheme(storage?: <T>(key: string, initial: T) => Ref<T>, options?: DaisyThemeOptions) {
44
- // Use SSR-safe state that hydrates properly
45
- const themes = useSSRState('daisy-themes', () => options?.themes?.map(normalizeTheme) ?? [])
60
+ // Shared themes list — SSR-safe via useState in Nuxt, shared ref otherwise
61
+ const themes = useSharedState<DaisyThemeMeta[]>('daisy-themes', () => options?.themes?.map(normalizeTheme) ?? [])
46
62
 
47
- // If options provided, update themes
63
+ // If options provided, update themes (covers the app.vue initialization call)
48
64
  if (options?.themes) {
49
65
  themes.value = options.themes.map(normalizeTheme)
50
66
  }
51
67
 
52
- // Theme name - use provided storage or reuse global ref
68
+ // Theme name all callers must share the same ref.
69
+ // When storage is provided (app.vue), it creates the canonical ref (e.g. cookie-backed).
70
+ // Subsequent callers without storage reuse that same ref.
53
71
  let theme: Ref<string>
54
72
  if (storage) {
55
- // Initialize with provided storage (e.g., useCookie in app.vue)
56
73
  theme = storage('theme', options?.defaultTheme ?? themes.value[0]?.theme ?? 'light')
57
- globalStorageRef = theme
58
- } else if (globalStorageRef) {
59
- // Reuse the existing storage ref
60
- theme = globalStorageRef
74
+ themeRef = theme
75
+ } else if (themeRef) {
76
+ theme = themeRef
61
77
  } else {
62
- // Fallback to SSR state if no storage was ever provided
63
- theme = useSSRState('daisy-theme', () => options?.defaultTheme ?? themes.value[0]?.theme ?? 'light')
64
- globalStorageRef = theme
78
+ theme = useSharedState<string>('daisy-theme', () => options?.defaultTheme ?? themes.value[0]?.theme ?? 'light')
79
+ themeRef = theme
65
80
  }
66
81
 
67
82
  // System dark mode
@@ -0,0 +1,23 @@
1
+ // ESM shim for the 'debug' package (CJS-only).
2
+ // micromark's dev build does `import createDebug from 'debug'` which fails
3
+ // when Vite serves the raw CJS file as ESM in the browser.
4
+ // This provides a no-op replacement for client-side use.
5
+ function debug() {
6
+ return function noop() {}
7
+ }
8
+ debug.enable = function () {}
9
+ debug.disable = function () {}
10
+ debug.enabled = function () { return false }
11
+ debug.log = function () {}
12
+ debug.formatArgs = function () {}
13
+ debug.save = function () {}
14
+ debug.load = function () { return undefined }
15
+ debug.useColors = function () { return false }
16
+ debug.destroy = function () {}
17
+ debug.colors = []
18
+ debug.names = []
19
+ debug.skips = []
20
+ debug.formatters = {}
21
+
22
+ export default debug
23
+ export { debug }
@@ -0,0 +1,19 @@
1
+ import { resolveComponent } from 'vue'
2
+
3
+ /**
4
+ * Resolves the `is` prop value for render functions.
5
+ * Must be called inside a setup() or render function context.
6
+ *
7
+ * If `is` is already a component object, returns it directly.
8
+ * If `is` is a PascalCase string, tries resolveComponent().
9
+ * Otherwise returns the string as-is (treated as HTML tag).
10
+ */
11
+ export function resolveIs(is: string | object): any {
12
+ if (typeof is !== 'string') return is
13
+ // PascalCase — try to resolve as a registered component
14
+ if (/^[A-Z]/.test(is)) {
15
+ const resolved = resolveComponent(is)
16
+ if (typeof resolved !== 'string') return resolved
17
+ }
18
+ return is
19
+ }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "5.0.12",
7
+ "version": "5.1.2",
8
8
  "packageManager": "pnpm@10.10.0",
9
9
  "author": "feathers.dev",
10
10
  "exports": {
@@ -24,13 +24,13 @@
24
24
  "module": "./src/index.ts",
25
25
  "types": "./src/index.d.ts",
26
26
  "files": [
27
- "src",
27
+ "README.md",
28
28
  "app/components",
29
29
  "app/composables",
30
30
  "app/utils",
31
- "nuxt.js",
32
31
  "nuxt.d.ts",
33
- "README.md"
32
+ "nuxt.js",
33
+ "src"
34
34
  ],
35
35
  "scripts": {
36
36
  "import-d1-dumps": "./import-d1-dumps.sh",
@@ -55,6 +55,7 @@
55
55
  "daisyui": "^5"
56
56
  },
57
57
  "dependencies": {
58
+ "@formkit/auto-animate": "^0.9.0",
58
59
  "@nuxt/content": "3.5.1",
59
60
  "@nuxt/eslint": "1.3.0",
60
61
  "@nuxt/fonts": "0.11.2",