@nuxt/ui 4.10.0 → 4.11.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 (117) hide show
  1. package/.nuxt/ui.static.css +11 -11
  2. package/README.md +1 -0
  3. package/cli/commands/make/locale.mjs +40 -11
  4. package/cli/templates.mjs +2 -2
  5. package/dist/module.d.mts +1 -1
  6. package/dist/module.json +2 -2
  7. package/dist/module.mjs +5 -2
  8. package/dist/runtime/components/AuthForm.d.vue.ts +7 -7
  9. package/dist/runtime/components/AuthForm.vue.d.ts +7 -7
  10. package/dist/runtime/components/Button.vue +11 -2
  11. package/dist/runtime/components/Carousel.d.vue.ts +6 -6
  12. package/dist/runtime/components/Carousel.vue.d.ts +6 -6
  13. package/dist/runtime/components/ChatMessages.d.vue.ts +2 -2
  14. package/dist/runtime/components/ChatMessages.vue.d.ts +2 -2
  15. package/dist/runtime/components/ChatPromptSubmit.d.vue.ts +2 -2
  16. package/dist/runtime/components/ChatPromptSubmit.vue.d.ts +2 -2
  17. package/dist/runtime/components/Checkbox.d.vue.ts +1 -1
  18. package/dist/runtime/components/Checkbox.vue +12 -6
  19. package/dist/runtime/components/Checkbox.vue.d.ts +1 -1
  20. package/dist/runtime/components/CheckboxGroup.d.vue.ts +6 -0
  21. package/dist/runtime/components/CheckboxGroup.vue +10 -4
  22. package/dist/runtime/components/CheckboxGroup.vue.d.ts +6 -0
  23. package/dist/runtime/components/Editor.vue +4 -1
  24. package/dist/runtime/components/Error.d.vue.ts +1 -1
  25. package/dist/runtime/components/Error.vue.d.ts +1 -1
  26. package/dist/runtime/components/FileUpload.vue +17 -10
  27. package/dist/runtime/components/Form.vue +1 -1
  28. package/dist/runtime/components/Input.vue +12 -7
  29. package/dist/runtime/components/InputDate.vue +12 -8
  30. package/dist/runtime/components/InputMenu.vue +25 -11
  31. package/dist/runtime/components/InputNumber.vue +22 -14
  32. package/dist/runtime/components/InputRating.vue +10 -7
  33. package/dist/runtime/components/InputTags.vue +12 -7
  34. package/dist/runtime/components/InputTime.vue +12 -7
  35. package/dist/runtime/components/Link.vue +61 -7
  36. package/dist/runtime/components/Listbox.vue +10 -6
  37. package/dist/runtime/components/Modal.vue +12 -5
  38. package/dist/runtime/components/NavigationMenu.vue +10 -10
  39. package/dist/runtime/components/PinInput.vue +13 -8
  40. package/dist/runtime/components/Popover.vue +0 -1
  41. package/dist/runtime/components/PricingTable.d.vue.ts +1 -1
  42. package/dist/runtime/components/PricingTable.vue.d.ts +1 -1
  43. package/dist/runtime/components/Progress.d.vue.ts +2 -1
  44. package/dist/runtime/components/Progress.vue +5 -6
  45. package/dist/runtime/components/Progress.vue.d.ts +2 -1
  46. package/dist/runtime/components/ProgressGroup.d.vue.ts +91 -0
  47. package/dist/runtime/components/ProgressGroup.vue +99 -0
  48. package/dist/runtime/components/ProgressGroup.vue.d.ts +91 -0
  49. package/dist/runtime/components/RadioGroup.d.vue.ts +7 -1
  50. package/dist/runtime/components/RadioGroup.vue +14 -5
  51. package/dist/runtime/components/RadioGroup.vue.d.ts +7 -1
  52. package/dist/runtime/components/Select.d.vue.ts +2 -0
  53. package/dist/runtime/components/Select.vue +23 -8
  54. package/dist/runtime/components/Select.vue.d.ts +2 -0
  55. package/dist/runtime/components/SelectMenu.d.vue.ts +3 -0
  56. package/dist/runtime/components/SelectMenu.vue +35 -14
  57. package/dist/runtime/components/SelectMenu.vue.d.ts +3 -0
  58. package/dist/runtime/components/Slider.vue +15 -8
  59. package/dist/runtime/components/Splitter.d.vue.ts +266 -0
  60. package/dist/runtime/components/Splitter.vue +99 -0
  61. package/dist/runtime/components/Splitter.vue.d.ts +266 -0
  62. package/dist/runtime/components/Switch.vue +8 -4
  63. package/dist/runtime/components/Table.vue +5 -5
  64. package/dist/runtime/components/Textarea.vue +17 -7
  65. package/dist/runtime/components/Theme.d.vue.ts +1 -1
  66. package/dist/runtime/components/Theme.vue +4 -3
  67. package/dist/runtime/components/Theme.vue.d.ts +1 -1
  68. package/dist/runtime/components/Tree.vue +1 -1
  69. package/dist/runtime/components/color-mode/ColorModeSelect.vue +1 -0
  70. package/dist/runtime/components/content/ContentNavigation.vue +8 -1
  71. package/dist/runtime/components/content/ContentToc.vue +4 -1
  72. package/dist/runtime/components/locale/LocaleSelect.vue +1 -0
  73. package/dist/runtime/components/prose/CodeTree.vue +31 -18
  74. package/dist/runtime/composables/useComponentProps.d.ts +1 -1
  75. package/dist/runtime/composables/useComponentProps.js +6 -0
  76. package/dist/runtime/composables/useFormField.d.ts +10 -4
  77. package/dist/runtime/composables/useFormField.js +10 -3
  78. package/dist/runtime/keyframes.css +1 -1
  79. package/dist/runtime/locale/da.js +1 -1
  80. package/dist/runtime/locale/de_at.js +7 -0
  81. package/dist/runtime/locale/de_ch.js +1 -1
  82. package/dist/runtime/locale/eu.js +1 -1
  83. package/dist/runtime/locale/fi.js +1 -1
  84. package/dist/runtime/locale/he.js +1 -1
  85. package/dist/runtime/locale/hi.js +1 -1
  86. package/dist/runtime/locale/index.d.ts +2 -1
  87. package/dist/runtime/locale/index.js +2 -1
  88. package/dist/runtime/locale/is.js +1 -1
  89. package/dist/runtime/locale/lb.js +1 -1
  90. package/dist/runtime/locale/tg.d.ts +3 -0
  91. package/dist/runtime/locale/{tj.js → tg.js} +1 -1
  92. package/dist/runtime/locale/ur.js +1 -1
  93. package/dist/runtime/types/form.d.ts +1 -1
  94. package/dist/runtime/types/html.d.ts +3 -1
  95. package/dist/runtime/types/index.d.ts +2 -0
  96. package/dist/runtime/types/index.js +2 -0
  97. package/dist/runtime/types/theme.d.ts +2 -0
  98. package/dist/runtime/types/tv.d.ts +6 -2
  99. package/dist/runtime/utils/form.d.ts +1 -1
  100. package/dist/runtime/utils/form.js +3 -1
  101. package/dist/runtime/utils/link-keys.d.ts +1 -0
  102. package/dist/runtime/utils/link-keys.js +40 -0
  103. package/dist/runtime/utils/link.d.ts +2 -1
  104. package/dist/runtime/utils/link.js +2 -40
  105. package/dist/runtime/utils/prefetch.d.ts +5 -0
  106. package/dist/runtime/utils/prefetch.js +45 -0
  107. package/dist/runtime/utils/search.js +11 -18
  108. package/dist/runtime/utils/tv.d.ts +1 -1
  109. package/dist/runtime/utils/tv.js +103 -25
  110. package/dist/runtime/vue/components/Icon.vue +5 -2
  111. package/dist/runtime/vue/components/color-mode/ColorModeSelect.vue +1 -0
  112. package/dist/shared/{ui.XkBrgXFP.mjs → ui.DCJ9twx8.mjs} +597 -220
  113. package/dist/unplugin.d.mts +1 -1
  114. package/dist/unplugin.mjs +22 -6
  115. package/dist/vite.mjs +4 -4
  116. package/package.json +54 -53
  117. /package/dist/runtime/locale/{tj.d.ts → de_at.d.ts} +0 -0
@@ -1,8 +1,12 @@
1
1
  import type { ClassValue, TVVariants, TVCompoundVariants, TVDefaultVariants } from 'tailwind-variants';
2
2
  /**
3
3
  * A function form for a slot class that **replaces** the slot's default classes
4
- * instead of merging onto them. It receives the slot's fully resolved default
5
- * class string and returns the classes to use in its place.
4
+ * instead of merging onto them, returning the classes to use in their place.
5
+ * In `app.config.ui` it receives the slot's own theme classes and replaces only
6
+ * those — `variants` and `compoundVariants` still apply on top. In `:ui` / `class`
7
+ * it runs after variant resolution, so it receives the fully resolved class
8
+ * string and replaces it, keeping only the plain classes passed alongside the
9
+ * replacer (e.g. `[() => 'text-xl', 'opacity-50']` resolves to both).
6
10
  * @example title: defaults => 'text-xl font-bold'
7
11
  */
8
12
  export type SlotClassReplacer = (defaults: string) => ClassValue;
@@ -4,6 +4,6 @@ import type { FormSchema, ValidateReturnSchema } from '../types/form';
4
4
  export declare function isSuperStructSchema(schema: any): schema is Struct<any, any>;
5
5
  export declare function isStandardSchema(schema: any): schema is StandardSchemaV1;
6
6
  export declare function validateStandardSchema(state: any, schema: StandardSchemaV1): Promise<ValidateReturnSchema<typeof state>>;
7
- export declare function validateSchema<T extends object>(state: T, schema: FormSchema<T>): Promise<ValidateReturnSchema<typeof state>>;
7
+ export declare function validateSchema<T extends object>(state: T, _schema: FormSchema<T>): Promise<ValidateReturnSchema<typeof state>>;
8
8
  export declare function getAtPath<T extends object>(data: T, path?: string): any;
9
9
  export declare function setAtPath<T extends object>(data: T, path: string, value: any): T;
@@ -1,3 +1,4 @@
1
+ import { toRaw } from "vue";
1
2
  export function isSuperStructSchema(schema) {
2
3
  return "schema" in schema && typeof schema.coercer === "function" && typeof schema.validator === "function" && typeof schema.refiner === "function";
3
4
  }
@@ -37,7 +38,8 @@ async function validateSuperstructSchema(state, schema) {
37
38
  result
38
39
  };
39
40
  }
40
- export function validateSchema(state, schema) {
41
+ export function validateSchema(state, _schema) {
42
+ const schema = toRaw(_schema);
41
43
  if (isStandardSchema(schema)) {
42
44
  return validateStandardSchema(state, schema);
43
45
  } else if (isSuperStructSchema(schema)) {
@@ -0,0 +1 @@
1
+ export declare const linkKeys: readonly ["active", "activeClass", "ariaCurrentValue", "as", "disabled", "download", "exact", "exactActiveClass", "exactHash", "exactQuery", "external", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "href", "hreflang", "inactiveClass", "locale", "media", "noPrefetch", "noRel", "onClick", "ping", "prefetch", "prefetchOn", "prefetchedClass", "referrerpolicy", "rel", "replace", "target", "title", "to", "trailingSlash", "type", "viewTransition"];
@@ -0,0 +1,40 @@
1
+ export const linkKeys = [
2
+ "active",
3
+ "activeClass",
4
+ "ariaCurrentValue",
5
+ "as",
6
+ "disabled",
7
+ "download",
8
+ "exact",
9
+ "exactActiveClass",
10
+ "exactHash",
11
+ "exactQuery",
12
+ "external",
13
+ "form",
14
+ "formaction",
15
+ "formenctype",
16
+ "formmethod",
17
+ "formnovalidate",
18
+ "formtarget",
19
+ "href",
20
+ "hreflang",
21
+ "inactiveClass",
22
+ "locale",
23
+ "media",
24
+ "noPrefetch",
25
+ "noRel",
26
+ "onClick",
27
+ "ping",
28
+ "prefetch",
29
+ "prefetchOn",
30
+ "prefetchedClass",
31
+ "referrerpolicy",
32
+ "rel",
33
+ "replace",
34
+ "target",
35
+ "title",
36
+ "to",
37
+ "trailingSlash",
38
+ "type",
39
+ "viewTransition"
40
+ ];
@@ -1,5 +1,6 @@
1
1
  import type { LinkProps } from '../components/Link.vue';
2
- export declare const linkKeys: readonly ["active", "activeClass", "ariaCurrentValue", "as", "disabled", "download", "exact", "exactActiveClass", "exactHash", "exactQuery", "external", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "href", "hreflang", "inactiveClass", "locale", "media", "noPrefetch", "noRel", "onClick", "ping", "prefetch", "prefetchOn", "prefetchedClass", "referrerpolicy", "rel", "replace", "target", "title", "to", "trailingSlash", "type", "viewTransition"];
2
+ import { linkKeys } from './link-keys';
3
+ export { linkKeys };
3
4
  export declare function pickLinkProps(link: LinkProps & {
4
5
  [key: string]: any;
5
6
  }): import("@vueuse/shared").ReactivePickReturn<LinkProps & {
@@ -1,45 +1,7 @@
1
1
  import { reactivePick } from "@vueuse/core";
2
2
  import { isEqual, diff } from "ohash/utils";
3
- export const linkKeys = [
4
- "active",
5
- "activeClass",
6
- "ariaCurrentValue",
7
- "as",
8
- "disabled",
9
- "download",
10
- "exact",
11
- "exactActiveClass",
12
- "exactHash",
13
- "exactQuery",
14
- "external",
15
- "form",
16
- "formaction",
17
- "formenctype",
18
- "formmethod",
19
- "formnovalidate",
20
- "formtarget",
21
- "href",
22
- "hreflang",
23
- "inactiveClass",
24
- "locale",
25
- "media",
26
- "noPrefetch",
27
- "noRel",
28
- "onClick",
29
- "ping",
30
- "prefetch",
31
- "prefetchOn",
32
- "prefetchedClass",
33
- "referrerpolicy",
34
- "rel",
35
- "replace",
36
- "target",
37
- "title",
38
- "to",
39
- "trailingSlash",
40
- "type",
41
- "viewTransition"
42
- ];
3
+ import { linkKeys } from "./link-keys.js";
4
+ export { linkKeys };
43
5
  export function pickLinkProps(link) {
44
6
  const keys = Object.keys(link);
45
7
  const ariaKeys = keys.filter((key) => key.startsWith("aria-"));
@@ -0,0 +1,5 @@
1
+ type IdleCallbackHandle = ReturnType<typeof setTimeout> | number;
2
+ export declare function requestIdleCallback(callback: () => void): IdleCallbackHandle | undefined;
3
+ export declare function cancelIdleCallback(handle: IdleCallbackHandle | undefined): void;
4
+ export declare function observeIntersection(element: Element, callback: () => void): () => void;
5
+ export {};
@@ -0,0 +1,45 @@
1
+ export function requestIdleCallback(callback) {
2
+ if (typeof window === "undefined") {
3
+ return;
4
+ }
5
+ if (typeof window.requestIdleCallback === "function") {
6
+ return window.requestIdleCallback(callback);
7
+ }
8
+ return setTimeout(callback, 1);
9
+ }
10
+ export function cancelIdleCallback(handle) {
11
+ if (typeof window === "undefined" || handle === void 0) {
12
+ return;
13
+ }
14
+ if (typeof window.cancelIdleCallback === "function") {
15
+ window.cancelIdleCallback(handle);
16
+ return;
17
+ }
18
+ clearTimeout(handle);
19
+ }
20
+ let observer = null;
21
+ const callbacks = /* @__PURE__ */ new Map();
22
+ export function observeIntersection(element, callback) {
23
+ if (typeof IntersectionObserver === "undefined") {
24
+ return () => {
25
+ };
26
+ }
27
+ observer ||= new IntersectionObserver((entries) => {
28
+ for (const entry of entries) {
29
+ const callback2 = callbacks.get(entry.target);
30
+ if ((entry.isIntersecting || entry.intersectionRatio > 0) && callback2) {
31
+ callback2();
32
+ }
33
+ }
34
+ });
35
+ callbacks.set(element, callback);
36
+ observer.observe(element);
37
+ return () => {
38
+ callbacks.delete(element);
39
+ observer?.unobserve(element);
40
+ if (callbacks.size === 0) {
41
+ observer?.disconnect();
42
+ observer = null;
43
+ }
44
+ };
45
+ }
@@ -8,32 +8,25 @@ const htmlEscapes = {
8
8
  function escapeHTML(str) {
9
9
  return str.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
10
10
  }
11
- function isAlreadyEscaped(str) {
12
- return /&(?:amp|lt|gt|quot|#39);/.test(str);
13
- }
14
- function sanitize(str) {
15
- if (isAlreadyEscaped(str)) {
16
- return str;
17
- }
18
- return escapeHTML(str);
19
- }
20
11
  function truncateHTMLFromStart(html, maxLength) {
21
12
  let truncated = "";
22
13
  let totalLength = 0;
23
14
  let insideTag = false;
24
- for (let i = html.length - 1; i >= 0; i--) {
25
- if (html[i] === ">") {
15
+ const chars = Array.from(html);
16
+ for (let i = chars.length - 1; i >= 0; i--) {
17
+ const char = chars[i];
18
+ if (char === ">") {
26
19
  insideTag = true;
27
- } else if (html[i] === "<") {
20
+ } else if (char === "<") {
28
21
  insideTag = false;
29
- truncated = html[i] + truncated;
22
+ truncated = char + truncated;
30
23
  continue;
31
24
  }
32
25
  if (!insideTag) {
33
26
  totalLength++;
34
27
  }
35
28
  if (totalLength <= maxLength) {
36
- truncated = html[i] + truncated;
29
+ truncated = char + truncated;
37
30
  } else {
38
31
  truncated = "..." + truncated;
39
32
  break;
@@ -62,17 +55,17 @@ export function highlight(item, searchTerm, forceKey, omitKeys, useTokenSearch)
62
55
  const lastIndiceNextIndex = region[1] + 1;
63
56
  const isMatched = lastIndiceNextIndex - region[0] >= minTokenLength;
64
57
  content += [
65
- sanitize(value.substring(nextUnhighlightedRegionStartingIndex, region[0])),
58
+ escapeHTML(value.substring(nextUnhighlightedRegionStartingIndex, region[0])),
66
59
  isMatched && `<mark>`,
67
- sanitize(value.substring(region[0], lastIndiceNextIndex)),
60
+ escapeHTML(value.substring(region[0], lastIndiceNextIndex)),
68
61
  isMatched && "</mark>"
69
62
  ].filter(Boolean).join("");
70
63
  nextUnhighlightedRegionStartingIndex = lastIndiceNextIndex;
71
64
  });
72
- content += sanitize(value.substring(nextUnhighlightedRegionStartingIndex));
65
+ content += escapeHTML(value.substring(nextUnhighlightedRegionStartingIndex));
73
66
  const markIndex = content.indexOf("<mark>");
74
67
  if (markIndex !== -1) {
75
- content = truncateHTMLFromStart(content, content.length - markIndex);
68
+ content = truncateHTMLFromStart(content, Array.from(content.slice(markIndex)).length);
76
69
  }
77
70
  return content;
78
71
  }
@@ -34,7 +34,7 @@ type WideTV = {
34
34
  * Wraps `tailwind-variants`' `tv` so slot classes can be **replaced** (not just
35
35
  * merged) through a function form — `(defaults) => classes` — in `:ui`, the
36
36
  * `class` prop and `app.config.ui`. The wrapper is transparent for every other
37
- * usage: it preserves the `TVReturnType` (so `extend: tv(theme)` keeps working
37
+ * usage: it preserves the `TVReturnType` (so `extend: theme` keeps working
38
38
  * via property reads) and only intercepts the slot functions on invocation.
39
39
  */
40
40
  export declare const tv: WideTV;
@@ -29,7 +29,44 @@ function plainClasses(value) {
29
29
  function applyReplacer(replacer, slotProps, resolveDefaults) {
30
30
  return cnMerge(replacer(resolveDefaults()), ...plainClasses(slotProps.class), ...plainClasses(slotProps.className))(config) ?? "";
31
31
  }
32
- function wrapSlots(slots, directives) {
32
+ function isMemoizable(value, depth = 0) {
33
+ if (value === void 0 || value === null) {
34
+ return true;
35
+ }
36
+ const type = typeof value;
37
+ if (type === "string" || type === "boolean") {
38
+ return true;
39
+ }
40
+ if (type === "number") {
41
+ return Number.isFinite(value);
42
+ }
43
+ if (Array.isArray(value)) {
44
+ if (depth >= 4) {
45
+ return false;
46
+ }
47
+ for (const item of value) {
48
+ if (!isMemoizable(item, depth + 1)) {
49
+ return false;
50
+ }
51
+ }
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ function memoKey(slotProps) {
57
+ const proto = Object.getPrototypeOf(slotProps);
58
+ if (proto !== Object.prototype && proto !== null) {
59
+ return void 0;
60
+ }
61
+ for (const key of Object.keys(slotProps)) {
62
+ if (!isMemoizable(slotProps[key])) {
63
+ return void 0;
64
+ }
65
+ }
66
+ return JSON.stringify(slotProps);
67
+ }
68
+ function wrapSlots(slots) {
69
+ const memo = /* @__PURE__ */ new Map();
33
70
  return new Proxy(slots, {
34
71
  get(target, key) {
35
72
  const slot = target[key];
@@ -37,52 +74,93 @@ function wrapSlots(slots, directives) {
37
74
  return slot;
38
75
  }
39
76
  return (slotProps = {}) => {
40
- const replacer = findReplacer(slotProps.class) ?? findReplacer(slotProps.className) ?? directives?.[key];
77
+ const replacer = findReplacer(slotProps.class) ?? findReplacer(slotProps.className);
41
78
  if (!replacer) {
42
- return slot(slotProps);
79
+ const cacheKey = memoKey(slotProps);
80
+ if (cacheKey === void 0) {
81
+ return slot(slotProps);
82
+ }
83
+ let cache = memo.get(key);
84
+ if (!cache) {
85
+ cache = /* @__PURE__ */ new Map();
86
+ memo.set(key, cache);
87
+ }
88
+ let result = cache.get(cacheKey);
89
+ if (result === void 0 && !cache.has(cacheKey)) {
90
+ if (cache.size >= 500) {
91
+ cache.clear();
92
+ }
93
+ result = slot(slotProps);
94
+ cache.set(cacheKey, result);
95
+ }
96
+ return result;
43
97
  }
44
98
  return applyReplacer(replacer, slotProps, () => slot({ ...slotProps, class: void 0, className: void 0 }));
45
99
  };
46
100
  }
47
101
  });
48
102
  }
49
- function extractDirectives(componentConfig) {
103
+ function defaultClasses(value) {
104
+ return cnMerge(value)(config) ?? "";
105
+ }
106
+ function resolveReplacers(componentConfig) {
50
107
  if (!componentConfig || typeof componentConfig !== "object") {
51
- return { config: componentConfig };
52
- }
53
- let config2 = componentConfig;
54
- let directives;
55
- if (typeof componentConfig.base === "function") {
56
- directives = { base: componentConfig.base };
57
- config2 = { ...config2, base: "" };
108
+ return componentConfig;
58
109
  }
59
110
  const slots = componentConfig.slots;
60
- if (slots && typeof slots === "object") {
61
- const replacers = Object.entries(slots).filter(([, value]) => typeof value === "function");
62
- if (replacers.length) {
63
- directives ??= {};
64
- const cleaned = { ...slots };
65
- for (const [slot, replacer] of replacers) {
66
- directives[slot] = replacer;
67
- cleaned[slot] = "";
111
+ const replacers = slots && typeof slots === "object" ? Object.entries(slots).filter((entry) => typeof entry[1] === "function") : [];
112
+ const baseReplacer = typeof componentConfig.base === "function" ? componentConfig.base : void 0;
113
+ if (!replacers.length && !baseReplacer) {
114
+ return componentConfig;
115
+ }
116
+ const extend = componentConfig.extend;
117
+ const resolved = { ...componentConfig };
118
+ let extendSlots;
119
+ let blankExtendBase = false;
120
+ if (baseReplacer) {
121
+ resolved.base = baseReplacer(defaultClasses(extend?.slots?.base ?? extend?.base));
122
+ if (extend?.slots?.base) {
123
+ extendSlots ??= { ...extend.slots };
124
+ extendSlots.base = "";
125
+ }
126
+ if (extend?.base) {
127
+ blankExtendBase = true;
128
+ }
129
+ }
130
+ if (replacers.length) {
131
+ const cleaned = { ...slots };
132
+ for (const [slot, replacer] of replacers) {
133
+ cleaned[slot] = replacer(defaultClasses(extend?.slots?.[slot]));
134
+ if (extend?.slots?.[slot]) {
135
+ extendSlots ??= { ...extend.slots };
136
+ extendSlots[slot] = "";
68
137
  }
69
- config2 = { ...config2, slots: cleaned };
70
138
  }
139
+ resolved.slots = cleaned;
140
+ }
141
+ if (extendSlots || blankExtendBase) {
142
+ const cleanedExtend = { ...extend };
143
+ if (extendSlots) {
144
+ cleanedExtend.slots = extendSlots;
145
+ }
146
+ if (blankExtendBase) {
147
+ cleanedExtend.base = "";
148
+ }
149
+ resolved.extend = cleanedExtend;
71
150
  }
72
- return { config: config2, directives };
151
+ return resolved;
73
152
  }
74
153
  export const tv = ((componentConfig) => {
75
- const { config: cleanConfig, directives } = extractDirectives(componentConfig);
76
- const component = baseTv(cleanConfig);
154
+ const component = baseTv(resolveReplacers(componentConfig));
77
155
  return new Proxy(component, {
78
156
  apply(target, thisArg, args) {
79
157
  const result = Reflect.apply(target, thisArg, args);
80
158
  if (result && typeof result === "object") {
81
- return wrapSlots(result, directives);
159
+ return wrapSlots(result);
82
160
  }
83
161
  if (typeof result === "string") {
84
162
  const slotProps = args[0] ?? {};
85
- const replacer = findReplacer(slotProps.class) ?? findReplacer(slotProps.className) ?? directives?.base;
163
+ const replacer = findReplacer(slotProps.class) ?? findReplacer(slotProps.className);
86
164
  if (replacer) {
87
165
  return applyReplacer(replacer, slotProps, () => Reflect.apply(target, thisArg, [{ ...slotProps, class: void 0, className: void 0 }]));
88
166
  }
@@ -4,7 +4,7 @@
4
4
 
5
5
  <script setup>
6
6
  import { computed } from "vue";
7
- import { Icon as IconifyIcon } from "@iconify/vue";
7
+ import { Icon as IconifyIcon, iconLoaded } from "@iconify/vue";
8
8
  import { useAppConfig } from "#imports";
9
9
  const props = defineProps({
10
10
  name: { type: null, required: true },
@@ -25,16 +25,19 @@ const mode = computed(() => {
25
25
  });
26
26
  const size = computed(() => props.size || appConfig.icon?.size);
27
27
  const customize = computed(() => resolveCustomizeFn(props.customize, appConfig.icon?.customize));
28
+ const icon = computed(() => typeof props.name === "string" ? props.name.replace(/^i-/, "") : "");
29
+ const ssr = computed(() => iconLoaded(icon.value));
28
30
  </script>
29
31
 
30
32
  <template>
31
33
  <IconifyIcon
32
34
  v-if="typeof name === 'string'"
33
- :icon="name.replace(/^i-/, '')"
35
+ :icon="icon"
34
36
  :mode="mode"
35
37
  :width="size"
36
38
  :height="size"
37
39
  :customise="customize"
40
+ :ssr="ssr"
38
41
  />
39
42
  <component :is="name" v-else />
40
43
  </template>
@@ -32,6 +32,7 @@ const props = defineProps({
32
32
  modelModifiers: { type: null, required: false },
33
33
  multiple: { type: Boolean, required: false },
34
34
  highlight: { type: Boolean, required: false },
35
+ fixed: { type: Boolean, required: false },
35
36
  createItem: { type: [Boolean, String, Object], required: false },
36
37
  filterFields: { type: Array, required: false },
37
38
  ignoreFilter: { type: Boolean, required: false },