@epoch32/visage 1.1.5 → 1.3.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/src/ui/index.ts CHANGED
@@ -10,6 +10,22 @@ export {
10
10
  useAccordionContext,
11
11
  useAccordionItemContext
12
12
  } from "./accordion";
13
+ export {
14
+ BottomBar,
15
+ BottomBarAction,
16
+ type BottomBarActionProps,
17
+ BottomBarBadge,
18
+ type BottomBarBadgeProps,
19
+ type BottomBarContextValue,
20
+ BottomBarItem,
21
+ type BottomBarItemConfig,
22
+ type BottomBarItemProps,
23
+ type BottomBarProps,
24
+ BottomBarRoot,
25
+ BottomBarSeparator,
26
+ type BottomBarSeparatorProps,
27
+ useBottomBarContext
28
+ } from "./bottom-bar";
13
29
  export {
14
30
  Command,
15
31
  CommandDialog,
@@ -48,6 +48,9 @@ function parseNamedImports(importClause: string): ParsedImport[] {
48
48
  * });
49
49
  * ```
50
50
  */
51
+ const VIRTUAL_PREFIX = "virtual:visage-icons";
52
+ const RESOLVED_PREFIX = `\0${VIRTUAL_PREFIX}`;
53
+
51
54
  export function visageLucide(options: VisageLucideOptions = {}): VisageVitePlugin {
52
55
  const aliases = options.aliases ?? ["lucide-react"];
53
56
 
@@ -58,12 +61,15 @@ export function visageLucide(options: VisageLucideOptions = {}): VisageVitePlugi
58
61
  config() {
59
62
  return {
60
63
  optimizeDeps: {
61
- exclude: aliases
64
+ exclude: [...aliases, VIRTUAL_PREFIX]
62
65
  }
63
66
  };
64
67
  },
65
68
 
66
69
  resolveId(id: string) {
70
+ if (id.startsWith(VIRTUAL_PREFIX)) {
71
+ return `\0${id}`;
72
+ }
67
73
  if (aliases.includes(id)) {
68
74
  return `\0visage-lucide:${id}`;
69
75
  }
@@ -71,6 +77,22 @@ export function visageLucide(options: VisageLucideOptions = {}): VisageVitePlugi
71
77
  },
72
78
 
73
79
  load(id: string) {
80
+ if (id.startsWith(RESOLVED_PREFIX)) {
81
+ const query = id.slice(RESOLVED_PREFIX.length);
82
+ const params = new URLSearchParams(query.startsWith("?") ? query.slice(1) : "");
83
+ const names = (params.get("icons") || "")
84
+ .split(",")
85
+ .map((s) => s.trim())
86
+ .filter(Boolean);
87
+
88
+ const imports = names.map((n) => `${n} as __icon_node_${n}`).join(", ");
89
+ const exports = names
90
+ .map((n) => `export const ${n} = /* @__PURE__ */ createIcon("${n}", __icon_node_${n});`)
91
+ .join("\n");
92
+
93
+ return `import { createIcon } from "visage/ui";\nimport { ${imports} } from "lucide";\n\n${exports}\n`;
94
+ }
95
+
74
96
  if (id.startsWith("\0visage-lucide:")) {
75
97
  return `
76
98
  import * as lucideIcons from "lucide";
@@ -88,10 +110,6 @@ export const __getIcon = (name) => {
88
110
  export default new Proxy({}, {
89
111
  get: (_, prop) => typeof prop === "string" ? __getIcon(prop) : undefined
90
112
  });
91
-
92
- // Dynamic proxy export for all lucide icon names
93
- ${Object.keys({})};
94
- export * from "lucide";
95
113
  `;
96
114
  }
97
115
  return null;
@@ -106,26 +124,48 @@ export * from "lucide";
106
124
  let hasMatches = false;
107
125
 
108
126
  for (const alias of aliases) {
109
- // Regex to match: import { ... } from "lucide-react" or 'lucide-react'
110
- const regex = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*['"]${alias}['"];?`, "g");
111
-
112
- transformed = transformed.replace(regex, (_match, importClause) => {
127
+ // Match: import { ... } from "alias"
128
+ const importRegex = new RegExp(
129
+ `import\\s*\\{([^}]+)\\}\\s*from\\s*['"]${alias}['"];?`,
130
+ "g"
131
+ );
132
+ transformed = transformed.replace(importRegex, (_match, importClause) => {
113
133
  const imports = parseNamedImports(importClause);
114
134
  if (imports.length === 0) return "";
115
-
116
135
  hasMatches = true;
117
136
 
118
- const lucideNamedImports = imports
119
- .map((imp) => `${imp.importedName} as __icon_node_${imp.importedName}`)
137
+ const queryIcons = Array.from(new Set(imports.map((i) => i.importedName))).join(",");
138
+ const specifiers = imports
139
+ .map((i) =>
140
+ i.importedName === i.localName
141
+ ? i.importedName
142
+ : `${i.importedName} as ${i.localName}`
143
+ )
120
144
  .join(", ");
121
145
 
122
- const componentDeclarations = imports
123
- .map((imp) => {
124
- return `const ${imp.localName} = /* @__PURE__ */ __visageCreateIcon("${imp.importedName}", __icon_node_${imp.importedName});`;
125
- })
126
- .join("\n");
146
+ return `import { ${specifiers} } from "${VIRTUAL_PREFIX}?icons=${queryIcons}";`;
147
+ });
148
+
149
+ // Match: export { ... } from "alias"
150
+ const exportRegex = new RegExp(
151
+ `export\\s*\\{([^}]+)\\}\\s*from\\s*['"]${alias}['"];?`,
152
+ "g"
153
+ );
154
+ transformed = transformed.replace(exportRegex, (_match, exportClause) => {
155
+ const exports = parseNamedImports(exportClause);
156
+ if (exports.length === 0) return "";
157
+ hasMatches = true;
158
+
159
+ const queryIcons = Array.from(new Set(exports.map((i) => i.importedName))).join(",");
160
+ const specifiers = exports
161
+ .map((i) =>
162
+ i.importedName === i.localName
163
+ ? i.importedName
164
+ : `${i.importedName} as ${i.localName}`
165
+ )
166
+ .join(", ");
127
167
 
128
- return `import { createIcon as __visageCreateIcon } from "visage/ui";\nimport { ${lucideNamedImports} } from "lucide";\n${componentDeclarations}`;
168
+ return `export { ${specifiers} } from "${VIRTUAL_PREFIX}?icons=${queryIcons}";`;
129
169
  });
130
170
  }
131
171