@brickflow/ui 0.0.40 → 0.0.43

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 (38) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +3 -0
  3. package/dist/runtime/components/Button/icons.demo.vue +9 -9
  4. package/dist/runtime/components/Button/index.vue +83 -57
  5. package/dist/runtime/components/Button/size.demo.vue +35 -66
  6. package/dist/runtime/components/Button/slots.demo.vue +10 -8
  7. package/dist/runtime/components/Button/state.demo.vue +58 -8
  8. package/dist/runtime/components/Button/variants.demo.vue +18 -20
  9. package/dist/runtime/components/Icon/basic.demo.vue +13 -10
  10. package/dist/runtime/components/Icon/gallery.demo.vue +142 -0
  11. package/dist/runtime/components/Icon/index.vue +15 -9
  12. package/dist/runtime/components/Link/basic.demo.vue +7 -7
  13. package/dist/runtime/components/Link/index.vue +81 -50
  14. package/dist/runtime/icon-font.d.ts +1 -0
  15. package/dist/runtime/pages/ui.vue +514 -347
  16. package/package.json +5 -5
  17. package/dist/runtime/components/Button/icons.demo.d.vue.ts +0 -8
  18. package/dist/runtime/components/Button/icons.demo.vue.d.ts +0 -8
  19. package/dist/runtime/components/Button/index.d.vue.ts +0 -51
  20. package/dist/runtime/components/Button/index.vue.d.ts +0 -51
  21. package/dist/runtime/components/Button/size.demo.d.vue.ts +0 -7
  22. package/dist/runtime/components/Button/size.demo.vue.d.ts +0 -7
  23. package/dist/runtime/components/Button/slots.demo.d.vue.ts +0 -7
  24. package/dist/runtime/components/Button/slots.demo.vue.d.ts +0 -7
  25. package/dist/runtime/components/Button/state.demo.d.vue.ts +0 -7
  26. package/dist/runtime/components/Button/state.demo.vue.d.ts +0 -7
  27. package/dist/runtime/components/Button/variants.demo.d.vue.ts +0 -7
  28. package/dist/runtime/components/Button/variants.demo.vue.d.ts +0 -7
  29. package/dist/runtime/components/Icon/basic.demo.d.vue.ts +0 -8
  30. package/dist/runtime/components/Icon/basic.demo.vue.d.ts +0 -8
  31. package/dist/runtime/components/Icon/index.d.vue.ts +0 -7
  32. package/dist/runtime/components/Icon/index.vue.d.ts +0 -7
  33. package/dist/runtime/components/Link/basic.demo.d.vue.ts +0 -8
  34. package/dist/runtime/components/Link/basic.demo.vue.d.ts +0 -8
  35. package/dist/runtime/components/Link/index.d.vue.ts +0 -51
  36. package/dist/runtime/components/Link/index.vue.d.ts +0 -51
  37. package/dist/runtime/pages/ui.d.vue.ts +0 -4
  38. package/dist/runtime/pages/ui.vue.d.ts +0 -4
@@ -1,348 +1,442 @@
1
- <script setup>
2
- import { useHead, useRoute, useRouter } from "nuxt/app";
3
- import { computed, nextTick, onMounted, ref, watch } from "vue";
4
- import { uiComponents } from "#brickflow-ui-catalog";
5
- import { uiThemeEnabled } from "#brickflow-ui-options";
6
- import { useTheme } from "../composables/useTheme";
7
- useHead({
8
- meta: [
9
- {
10
- content: "noindex, nofollow, noarchive",
11
- name: "robots"
12
- }
13
- ],
14
- title: "UI playground"
15
- });
16
- const route = useRoute();
17
- const router = useRouter();
18
- const expandedDemoCode = ref(/* @__PURE__ */ new Set());
19
- const isNavigationOpen = ref(false);
20
- const mobileNavigation = ref();
21
- const colorSwatchesReady = ref(false);
22
- const stylesExpanded = ref(false);
23
- const theme = uiThemeEnabled ? useTheme() : void 0;
24
- const isDark = computed(() => theme?.isDark.value ?? false);
25
- const toggleTheme = () => theme?.toggleTheme();
26
- const activeComponent = computed(() => {
27
- const component = route.query.component;
28
- const id = typeof component === "string" ? component : void 0;
29
- return uiComponents.find((item) => item.id === id) ?? uiComponents[0];
30
- });
31
- const visibleStyles = computed(() => {
32
- const styles = activeComponent.value?.styles ?? [];
33
- return stylesExpanded.value ? styles : styles.slice(0, 5);
34
- });
35
- const getDemoCodeKey = (demoId) => `${activeComponent.value?.id}:${demoId}`;
36
- const escapeHtml = (value) => value.replace(
37
- /[&<>"']/g,
38
- (character) => ({
39
- '"': "&quot;",
40
- "&": "&amp;",
41
- "'": "&#39;",
42
- "<": "&lt;",
43
- ">": "&gt;"
44
- })[character] ?? character
45
- );
46
- const token = (className, value) => `<span class="${className}">${value}</span>`;
47
- const highlightTypeScript = (source) => {
48
- const pattern = /\/\*[\s\S]*?\*\/|\/\/[^\n]*|`(?:\\[\s\S]|[^`])*`|'(?:\\[\s\S]|[^'])*'|"(?:\\[\s\S]|[^"])*"|\b(?:as|async|await|const|export|from|function|import|interface|let|return|type)\b|\b\d+(?:\.\d+)?\b/g;
49
- let html = "";
50
- let lastIndex = 0;
51
- for (const match of source.matchAll(pattern)) {
52
- const index = match.index ?? 0;
53
- const value = match[0];
54
- html += escapeHtml(source.slice(lastIndex, index));
55
- if (value.startsWith("//") || value.startsWith("/*")) {
56
- html += token("ui-code-comment", escapeHtml(value));
57
- } else if (value.startsWith("'") || value.startsWith('"') || value.startsWith("`")) {
58
- html += token("ui-code-string", escapeHtml(value));
59
- } else if (/^\d/.test(value)) {
60
- html += token("ui-code-number", value);
61
- } else {
62
- html += token("ui-code-keyword", value);
1
+ <script lang="ts" setup>
2
+ import { useHead, useRoute, useRouter } from 'nuxt/app'
3
+ import { computed, nextTick, onMounted, ref, watch } from 'vue'
4
+
5
+ import { uiComponents } from '#brickflow-ui-catalog'
6
+ import { uiThemeEnabled } from '#brickflow-ui-options'
7
+
8
+ import { useTheme } from '../composables/useTheme'
9
+
10
+ useHead({
11
+ meta: [
12
+ {
13
+ content: 'noindex, nofollow, noarchive',
14
+ name: 'robots',
15
+ },
16
+ ],
17
+ title: 'UI playground',
18
+ })
19
+
20
+ const route = useRoute()
21
+ const router = useRouter()
22
+ const expandedDemoCode = ref(new Set<string>())
23
+ const isNavigationOpen = ref(false)
24
+ const mobileNavigation = ref<HTMLElement>()
25
+ const colorSwatchesReady = ref(false)
26
+ const stylesExpanded = ref(false)
27
+ const theme = uiThemeEnabled ? useTheme() : undefined
28
+ const isDark = computed(() => theme?.isDark.value ?? false)
29
+ const toggleTheme = (): void => theme?.toggleTheme()
30
+
31
+ const activeComponent = computed(() => {
32
+ const component = route.query.component
33
+ const id = typeof component === 'string' ? component : undefined
34
+
35
+ return uiComponents.find((item) => item.id === id) ?? uiComponents[0]
36
+ })
37
+
38
+ const visibleStyles = computed(() => {
39
+ const styles = activeComponent.value?.styles ?? []
40
+
41
+ return stylesExpanded.value ? styles : styles.slice(0, 5)
42
+ })
43
+
44
+ const getDemoCodeKey = (demoId: string): string => `${activeComponent.value?.id}:${demoId}`
45
+
46
+ const escapeHtml = (value: string): string =>
47
+ value.replace(
48
+ /[&<>"']/g,
49
+ (character) =>
50
+ ({
51
+ '"': '&quot;',
52
+ '&': '&amp;',
53
+ "'": '&#39;',
54
+ '<': '&lt;',
55
+ '>': '&gt;',
56
+ })[character] ?? character,
57
+ )
58
+
59
+ const token = (className: string, value: string): string => `<span class="${className}">${value}</span>`
60
+
61
+ const highlightTypeScript = (source: string): string => {
62
+ const pattern =
63
+ /\/\*[\s\S]*?\*\/|\/\/[^\n]*|`(?:\\[\s\S]|[^`])*`|'(?:\\[\s\S]|[^'])*'|"(?:\\[\s\S]|[^"])*"|\b(?:as|async|await|const|export|from|function|import|interface|let|return|type)\b|\b\d+(?:\.\d+)?\b/g
64
+ let html = ''
65
+ let lastIndex = 0
66
+
67
+ for (const match of source.matchAll(pattern)) {
68
+ const index = match.index ?? 0
69
+ const value = match[0]
70
+ html += escapeHtml(source.slice(lastIndex, index))
71
+
72
+ if (value.startsWith('//') || value.startsWith('/*')) {
73
+ html += token('ui-code-comment', escapeHtml(value))
74
+ } else if (value.startsWith("'") || value.startsWith('"') || value.startsWith('`')) {
75
+ html += token('ui-code-string', escapeHtml(value))
76
+ } else if (/^\d/.test(value)) {
77
+ html += token('ui-code-number', value)
78
+ } else {
79
+ html += token('ui-code-keyword', value)
80
+ }
81
+
82
+ lastIndex = index + value.length
63
83
  }
64
- lastIndex = index + value.length;
84
+
85
+ return html + escapeHtml(source.slice(lastIndex))
65
86
  }
66
- return html + escapeHtml(source.slice(lastIndex));
67
- };
68
- const highlightPropType = (source) => {
69
- const pattern = /`(?:\\[\s\S]|[^`])*`|'(?:\\[\s\S]|[^'])*'|"(?:\\[\s\S]|[^"])*"|\b(?:any|bigint|boolean|never|null|number|object|string|symbol|undefined|unknown|void)\b|\b[A-Z]\w*\b|\|/g;
70
- let html = "";
71
- let lastIndex = 0;
72
- for (const match of source.matchAll(pattern)) {
73
- const index = match.index ?? 0;
74
- const value = match[0];
75
- html += escapeHtml(source.slice(lastIndex, index));
76
- if (value.startsWith("'") || value.startsWith('"') || value.startsWith("`")) {
77
- html += token("ui-code-string", escapeHtml(value));
78
- } else if (value === "|") {
79
- html += token("ui-code-punctuation", value);
80
- } else if (/^[A-Z]/.test(value)) {
81
- html += token("ui-code-tag", escapeHtml(value));
82
- } else {
83
- html += token("ui-code-keyword", value);
87
+
88
+ const highlightPropType = (source: string): string => {
89
+ const pattern =
90
+ /`(?:\\[\s\S]|[^`])*`|'(?:\\[\s\S]|[^'])*'|"(?:\\[\s\S]|[^"])*"|\b(?:any|bigint|boolean|never|null|number|object|string|symbol|undefined|unknown|void)\b|\b[A-Z]\w*\b|\|/g
91
+ let html = ''
92
+ let lastIndex = 0
93
+
94
+ for (const match of source.matchAll(pattern)) {
95
+ const index = match.index ?? 0
96
+ const value = match[0]
97
+ html += escapeHtml(source.slice(lastIndex, index))
98
+
99
+ if (value.startsWith("'") || value.startsWith('"') || value.startsWith('`')) {
100
+ html += token('ui-code-string', escapeHtml(value))
101
+ } else if (value === '|') {
102
+ html += token('ui-code-punctuation', value)
103
+ } else if (/^[A-Z]/.test(value)) {
104
+ html += token('ui-code-tag', escapeHtml(value))
105
+ } else {
106
+ html += token('ui-code-keyword', value)
107
+ }
108
+
109
+ lastIndex = index + value.length
84
110
  }
85
- lastIndex = index + value.length;
86
- }
87
- return html + escapeHtml(source.slice(lastIndex));
88
- };
89
- const highlightTag = (source) => {
90
- const opening = source.match(/^<(\/)?([\w.-]+)/);
91
- const closing = source.match(/\/?>\s*$/);
92
- if (!opening || !closing) {
93
- return escapeHtml(source);
94
- }
95
- const attributes = source.slice(opening[0].length, source.length - closing[0].length);
96
- let html = token("ui-code-punctuation", "&lt;");
97
- let attributeIndex = 0;
98
- if (opening[1]) {
99
- html += token("ui-code-punctuation", "/");
111
+
112
+ return html + escapeHtml(source.slice(lastIndex))
100
113
  }
101
- html += token("ui-code-tag", escapeHtml(opening[2] ?? ""));
102
- while (attributeIndex < attributes.length) {
103
- const character = attributes[attributeIndex] ?? "";
104
- if (/\s/.test(character)) {
105
- html += escapeHtml(character);
106
- attributeIndex += 1;
107
- continue;
108
- }
109
- const nameStart = attributeIndex;
110
- while (attributeIndex < attributes.length && !/[\s=]/.test(attributes[attributeIndex] ?? "")) {
111
- attributeIndex += 1;
112
- }
113
- const name = attributes.slice(nameStart, attributeIndex);
114
- html += token("ui-code-attribute", escapeHtml(name));
115
- const whitespaceStart = attributeIndex;
116
- while (/\s/.test(attributes[attributeIndex] ?? "")) {
117
- attributeIndex += 1;
118
- }
119
- html += escapeHtml(attributes.slice(whitespaceStart, attributeIndex));
120
- if (attributes[attributeIndex] !== "=") {
121
- continue;
114
+
115
+ const highlightTag = (source: string): string => {
116
+ const opening = source.match(/^<(\/)?([\w.-]+)/)
117
+ const closing = source.match(/\/?>\s*$/)
118
+
119
+ if (!opening || !closing) {
120
+ return escapeHtml(source)
122
121
  }
123
- html += token("ui-code-punctuation", "=");
124
- attributeIndex += 1;
125
- const valueWhitespaceStart = attributeIndex;
126
- while (/\s/.test(attributes[attributeIndex] ?? "")) {
127
- attributeIndex += 1;
122
+
123
+ const attributes = source.slice(opening[0].length, source.length - closing[0].length)
124
+ let html = token('ui-code-punctuation', '&lt;')
125
+ let attributeIndex = 0
126
+
127
+ if (opening[1]) {
128
+ html += token('ui-code-punctuation', '/')
128
129
  }
129
- html += escapeHtml(attributes.slice(valueWhitespaceStart, attributeIndex));
130
- const quote = attributes[attributeIndex];
131
- const valueStart = attributeIndex;
132
- if (quote === '"' || quote === "'") {
133
- attributeIndex += 1;
134
- while (attributeIndex < attributes.length && attributes[attributeIndex] !== quote) {
135
- attributeIndex += attributes[attributeIndex] === "\\" ? 2 : 1;
130
+
131
+ html += token('ui-code-tag', escapeHtml(opening[2] ?? ''))
132
+
133
+ while (attributeIndex < attributes.length) {
134
+ const character = attributes[attributeIndex] ?? ''
135
+ if (/\s/.test(character)) {
136
+ html += escapeHtml(character)
137
+ attributeIndex += 1
138
+ continue
136
139
  }
137
- attributeIndex += 1;
138
- } else {
139
- while (attributeIndex < attributes.length && !/\s/.test(attributes[attributeIndex] ?? "")) {
140
- attributeIndex += 1;
140
+
141
+ const nameStart = attributeIndex
142
+ while (attributeIndex < attributes.length && !/[\s=]/.test(attributes[attributeIndex] ?? '')) {
143
+ attributeIndex += 1
141
144
  }
142
- }
143
- html += token("ui-code-string", escapeHtml(attributes.slice(valueStart, attributeIndex)));
144
- }
145
- html += token("ui-code-punctuation", escapeHtml(closing[0]));
146
- return html;
147
- };
148
- const highlightTemplate = (source) => {
149
- let html = "";
150
- let index = 0;
151
- while (index < source.length) {
152
- const commentStart = source.indexOf("<!--", index);
153
- const interpolationStart = source.indexOf("{{", index);
154
- const tagStart = source.indexOf("<", index);
155
- const starts = [commentStart, interpolationStart, tagStart].filter((start2) => start2 !== -1);
156
- const start = Math.min(...starts);
157
- if (!Number.isFinite(start)) {
158
- return html + escapeHtml(source.slice(index));
159
- }
160
- html += escapeHtml(source.slice(index, start));
161
- if (start === commentStart) {
162
- const end = source.indexOf("-->", start + 4);
163
- if (end === -1) {
164
- return html + token("ui-code-comment", escapeHtml(source.slice(start)));
145
+
146
+ const name = attributes.slice(nameStart, attributeIndex)
147
+ html += token('ui-code-attribute', escapeHtml(name))
148
+
149
+ const whitespaceStart = attributeIndex
150
+ while (/\s/.test(attributes[attributeIndex] ?? '')) {
151
+ attributeIndex += 1
165
152
  }
166
- html += token("ui-code-comment", escapeHtml(source.slice(start, end + 3)));
167
- index = end + 3;
168
- } else if (start === interpolationStart) {
169
- const end = source.indexOf("}}", start + 2);
170
- if (end === -1) {
171
- return html + escapeHtml(source.slice(start));
153
+ html += escapeHtml(attributes.slice(whitespaceStart, attributeIndex))
154
+
155
+ if (attributes[attributeIndex] !== '=') {
156
+ continue
172
157
  }
173
- html += token("ui-code-punctuation", "{{");
174
- html += highlightTypeScript(source.slice(start + 2, end));
175
- html += token("ui-code-punctuation", "}}");
176
- index = end + 2;
177
- } else {
178
- let tagEnd = start + 1;
179
- let quote = "";
180
- while (tagEnd < source.length) {
181
- const character = source[tagEnd] ?? "";
182
- if (quote) {
183
- if (character === "\\") {
184
- tagEnd += 2;
185
- continue;
186
- }
187
- if (character === quote) {
188
- quote = "";
189
- }
190
- } else if (character === '"' || character === "'") {
191
- quote = character;
192
- } else if (character === ">") {
193
- break;
194
- }
195
- tagEnd += 1;
158
+
159
+ html += token('ui-code-punctuation', '=')
160
+ attributeIndex += 1
161
+
162
+ const valueWhitespaceStart = attributeIndex
163
+ while (/\s/.test(attributes[attributeIndex] ?? '')) {
164
+ attributeIndex += 1
196
165
  }
197
- const tag = source.slice(start, tagEnd + 1);
198
- if (/^<\/?[\w.-]/.test(tag)) {
199
- html += highlightTag(tag);
166
+ html += escapeHtml(attributes.slice(valueWhitespaceStart, attributeIndex))
167
+
168
+ const quote = attributes[attributeIndex]
169
+ const valueStart = attributeIndex
170
+ if (quote === '"' || quote === "'") {
171
+ attributeIndex += 1
172
+ while (attributeIndex < attributes.length && attributes[attributeIndex] !== quote) {
173
+ attributeIndex += attributes[attributeIndex] === '\\' ? 2 : 1
174
+ }
175
+ attributeIndex += 1
200
176
  } else {
201
- html += escapeHtml(tag);
177
+ while (attributeIndex < attributes.length && !/\s/.test(attributes[attributeIndex] ?? '')) {
178
+ attributeIndex += 1
179
+ }
202
180
  }
203
- index = tagEnd + 1;
181
+
182
+ html += token('ui-code-string', escapeHtml(attributes.slice(valueStart, attributeIndex)))
204
183
  }
184
+
185
+ html += token('ui-code-punctuation', escapeHtml(closing[0]))
186
+
187
+ return html
205
188
  }
206
- return html;
207
- };
208
- const highlightDemoCode = (source) => {
209
- const scriptPattern = /(<script\b[^>]*>)([\s\S]*?)(<\/script>)/g;
210
- let html = "";
211
- let lastIndex = 0;
212
- for (const match of source.matchAll(scriptPattern)) {
213
- const index = match.index ?? 0;
214
- html += highlightTemplate(source.slice(lastIndex, index));
215
- html += highlightTag(match[1] ?? "");
216
- html += highlightTypeScript(match[2] ?? "");
217
- html += highlightTag(match[3] ?? "");
218
- lastIndex = index + match[0].length;
219
- }
220
- return html + highlightTemplate(source.slice(lastIndex));
221
- };
222
- const highlightTailwindValue = (value) => {
223
- const pattern = /\d+(?:\.\d+)?/g;
224
- let html = "";
225
- let lastIndex = 0;
226
- for (const match of value.matchAll(pattern)) {
227
- const index = match.index ?? 0;
228
- html += token("ui-code-string", escapeHtml(value.slice(lastIndex, index)));
229
- html += token("ui-code-number", match[0]);
230
- lastIndex = index + match[0].length;
189
+
190
+ const highlightTemplate = (source: string): string => {
191
+ let html = ''
192
+ let index = 0
193
+
194
+ while (index < source.length) {
195
+ const commentStart = source.indexOf('<!--', index)
196
+ const interpolationStart = source.indexOf('{{', index)
197
+ const tagStart = source.indexOf('<', index)
198
+ const starts = [commentStart, interpolationStart, tagStart].filter((start) => start !== -1)
199
+ const start = Math.min(...starts)
200
+
201
+ if (!Number.isFinite(start)) {
202
+ return html + escapeHtml(source.slice(index))
203
+ }
204
+
205
+ html += escapeHtml(source.slice(index, start))
206
+
207
+ if (start === commentStart) {
208
+ const end = source.indexOf('-->', start + 4)
209
+ if (end === -1) {
210
+ return html + token('ui-code-comment', escapeHtml(source.slice(start)))
211
+ }
212
+
213
+ html += token('ui-code-comment', escapeHtml(source.slice(start, end + 3)))
214
+ index = end + 3
215
+ } else if (start === interpolationStart) {
216
+ const end = source.indexOf('}}', start + 2)
217
+ if (end === -1) {
218
+ return html + escapeHtml(source.slice(start))
219
+ }
220
+
221
+ html += token('ui-code-punctuation', '{{')
222
+ html += highlightTypeScript(source.slice(start + 2, end))
223
+ html += token('ui-code-punctuation', '}}')
224
+ index = end + 2
225
+ } else {
226
+ let tagEnd = start + 1
227
+ let quote = ''
228
+
229
+ while (tagEnd < source.length) {
230
+ const character = source[tagEnd] ?? ''
231
+ if (quote) {
232
+ if (character === '\\') {
233
+ tagEnd += 2
234
+ continue
235
+ }
236
+
237
+ if (character === quote) {
238
+ quote = ''
239
+ }
240
+ } else if (character === '"' || character === "'") {
241
+ quote = character
242
+ } else if (character === '>') {
243
+ break
244
+ }
245
+
246
+ tagEnd += 1
247
+ }
248
+
249
+ const tag = source.slice(start, tagEnd + 1)
250
+ if (/^<\/?[\w.-]/.test(tag)) {
251
+ html += highlightTag(tag)
252
+ } else {
253
+ html += escapeHtml(tag)
254
+ }
255
+ index = tagEnd + 1
256
+ }
257
+ }
258
+
259
+ return html
231
260
  }
232
- return html + token("ui-code-string", escapeHtml(value.slice(lastIndex)));
233
- };
234
- const getTailwindColorSwatch = (utility) => {
235
- const match = utility.match(
236
- /^(?:accent|bg|border|caret|decoration|divide|fill|from|outline|ring|shadow|stroke|text|to|via)-([a-z][a-z0-9-]*)(?:\/(\d{1,3}))?$/
237
- );
238
- if (!colorSwatchesReady.value || !match || typeof window === "undefined") {
239
- return "";
261
+
262
+ const highlightDemoCode = (source: string): string => {
263
+ const scriptPattern = /(<script\b[^>]*>)([\s\S]*?)(<\/script>)/g
264
+ let html = ''
265
+ let lastIndex = 0
266
+
267
+ for (const match of source.matchAll(scriptPattern)) {
268
+ const index = match.index ?? 0
269
+ html += highlightTemplate(source.slice(lastIndex, index))
270
+ html += highlightTag(match[1] ?? '')
271
+ html += highlightTypeScript(match[2] ?? '')
272
+ html += highlightTag(match[3] ?? '')
273
+ lastIndex = index + match[0].length
274
+ }
275
+
276
+ return html + highlightTemplate(source.slice(lastIndex))
240
277
  }
241
- const [, name, opacity] = match;
242
- const colorVariable = `--color-${name}`;
243
- const color = getComputedStyle(document.body).getPropertyValue(colorVariable).trim();
244
- if (!color || !CSS.supports("color", color)) {
245
- return "";
278
+
279
+ const highlightTailwindValue = (value: string): string => {
280
+ const pattern = /\d+(?:\.\d+)?/g
281
+ let html = ''
282
+ let lastIndex = 0
283
+
284
+ for (const match of value.matchAll(pattern)) {
285
+ const index = match.index ?? 0
286
+ html += token('ui-code-string', escapeHtml(value.slice(lastIndex, index)))
287
+ html += token('ui-code-number', match[0])
288
+ lastIndex = index + match[0].length
289
+ }
290
+
291
+ return html + token('ui-code-string', escapeHtml(value.slice(lastIndex)))
246
292
  }
247
- const opacityValue = opacity && Number(opacity) <= 100 ? Number(opacity) : void 0;
248
- const background = opacityValue ? `color-mix(in srgb, var(${colorVariable}) ${opacityValue}%, transparent)` : `var(${colorVariable})`;
249
- return `<span aria-hidden="true" class="ui-color-swatch" style="--ui-color-swatch: ${background}"></span>`;
250
- };
251
- const highlightTailwindUtility = (utility) => {
252
- let source = utility;
253
- let html = "";
254
- for (const prefix of ["!", "-"]) {
255
- if (source.startsWith(prefix)) {
256
- html += token("ui-code-punctuation", prefix);
257
- source = source.slice(prefix.length);
293
+
294
+ const getTailwindColorSwatch = (utility: string): string => {
295
+ const match = utility.match(
296
+ /^(?:accent|bg|border|caret|decoration|divide|fill|from|outline|ring|shadow|stroke|text|to|via)-([a-z][a-z0-9-]*)(?:\/(\d{1,3}))?$/,
297
+ )
298
+
299
+ if (!colorSwatchesReady.value || !match || typeof window === 'undefined') {
300
+ return ''
301
+ }
302
+
303
+ const [, name, opacity] = match
304
+ const colorVariable = `--color-${name}`
305
+ const color = getComputedStyle(document.body).getPropertyValue(colorVariable).trim()
306
+
307
+ if (!color || !CSS.supports('color', color)) {
308
+ return ''
258
309
  }
310
+
311
+ const opacityValue = opacity && Number(opacity) <= 100 ? Number(opacity) : undefined
312
+ const background = opacityValue
313
+ ? `color-mix(in srgb, var(${colorVariable}) ${opacityValue}%, transparent)`
314
+ : `var(${colorVariable})`
315
+
316
+ return `<span aria-hidden="true" class="ui-color-swatch" style="--ui-color-swatch: ${background}"></span>`
259
317
  }
260
- html += getTailwindColorSwatch(source);
261
- const separatorIndex = source.indexOf("-");
262
- if (separatorIndex === -1) {
263
- return html + token("ui-code-attribute", escapeHtml(source));
318
+
319
+ const highlightTailwindUtility = (utility: string): string => {
320
+ let source = utility
321
+ let html = ''
322
+
323
+ for (const prefix of ['!', '-']) {
324
+ if (source.startsWith(prefix)) {
325
+ html += token('ui-code-punctuation', prefix)
326
+ source = source.slice(prefix.length)
327
+ }
328
+ }
329
+
330
+ html += getTailwindColorSwatch(source)
331
+
332
+ const separatorIndex = source.indexOf('-')
333
+ if (separatorIndex === -1) {
334
+ return html + token('ui-code-attribute', escapeHtml(source))
335
+ }
336
+
337
+ html += token('ui-code-attribute', escapeHtml(source.slice(0, separatorIndex)))
338
+ html += token('ui-code-punctuation', '-')
339
+
340
+ return html + highlightTailwindValue(source.slice(separatorIndex + 1))
264
341
  }
265
- html += token("ui-code-attribute", escapeHtml(source.slice(0, separatorIndex)));
266
- html += token("ui-code-punctuation", "-");
267
- return html + highlightTailwindValue(source.slice(separatorIndex + 1));
268
- };
269
- const highlightTailwindClass = (className) => {
270
- const segments = [];
271
- let start = 0;
272
- let bracketDepth = 0;
273
- for (let index = 0; index < className.length; index += 1) {
274
- const character = className[index];
275
- if (character === "[") {
276
- bracketDepth += 1;
277
- } else if (character === "]") {
278
- bracketDepth = Math.max(0, bracketDepth - 1);
279
- } else if (character === ":" && bracketDepth === 0) {
280
- segments.push(className.slice(start, index));
281
- start = index + 1;
342
+
343
+ const highlightTailwindClass = (className: string): string => {
344
+ const segments: string[] = []
345
+ let start = 0
346
+ let bracketDepth = 0
347
+
348
+ for (let index = 0; index < className.length; index += 1) {
349
+ const character = className[index]
350
+
351
+ if (character === '[') {
352
+ bracketDepth += 1
353
+ } else if (character === ']') {
354
+ bracketDepth = Math.max(0, bracketDepth - 1)
355
+ } else if (character === ':' && bracketDepth === 0) {
356
+ segments.push(className.slice(start, index))
357
+ start = index + 1
358
+ }
282
359
  }
360
+
361
+ const utility = className.slice(start)
362
+ const variants = segments.map(
363
+ (segment) => `${token('ui-code-keyword', escapeHtml(segment))}${token('ui-code-punctuation', ':')}`,
364
+ )
365
+
366
+ return variants.join('') + highlightTailwindUtility(utility)
283
367
  }
284
- const utility = className.slice(start);
285
- const variants = segments.map(
286
- (segment) => `${token("ui-code-keyword", escapeHtml(segment))}${token("ui-code-punctuation", ":")}`
287
- );
288
- return variants.join("") + highlightTailwindUtility(utility);
289
- };
290
- const highlightStyleValue = (value) => {
291
- if (value === void 0) {
292
- return token("ui-code-comment", "\u2014");
368
+
369
+ const highlightStyleValue = (value: string | undefined): string => {
370
+ if (value === undefined) {
371
+ return token('ui-code-comment', '—')
372
+ }
373
+
374
+ if (value === '') {
375
+ return token('ui-code-string', '&quot;&quot;')
376
+ }
377
+
378
+ return value
379
+ .split(/(\s+)/)
380
+ .map((part) => (/\s/.test(part) ? escapeHtml(part) : highlightTailwindClass(part)))
381
+ .join('')
293
382
  }
294
- if (value === "") {
295
- return token("ui-code-string", "&quot;&quot;");
383
+
384
+ const isDemoCodeExpanded = (demoId: string): boolean => expandedDemoCode.value.has(getDemoCodeKey(demoId))
385
+
386
+ const toggleDemoCode = (demoId: string): void => {
387
+ const key = getDemoCodeKey(demoId)
388
+ const next = new Set(expandedDemoCode.value)
389
+
390
+ next.has(key) ? next.delete(key) : next.add(key)
391
+ expandedDemoCode.value = next
296
392
  }
297
- return value.split(/(\s+)/).map((part) => /\s/.test(part) ? escapeHtml(part) : highlightTailwindClass(part)).join("");
298
- };
299
- const isDemoCodeExpanded = (demoId) => expandedDemoCode.value.has(getDemoCodeKey(demoId));
300
- const toggleDemoCode = (demoId) => {
301
- const key = getDemoCodeKey(demoId);
302
- const next = new Set(expandedDemoCode.value);
303
- next.has(key) ? next.delete(key) : next.add(key);
304
- expandedDemoCode.value = next;
305
- };
306
- const closeNavigation = () => {
307
- isNavigationOpen.value = false;
308
- };
309
- onMounted(() => {
310
- colorSwatchesReady.value = true;
311
- });
312
- watch(isNavigationOpen, async (isOpen) => {
313
- if (isOpen) {
314
- await nextTick();
315
- mobileNavigation.value?.focus();
393
+
394
+ const closeNavigation = (): void => {
395
+ isNavigationOpen.value = false
316
396
  }
317
- });
318
- watch(
319
- () => route.query.component,
320
- (component) => {
321
- closeNavigation();
322
- window.scrollTo({ behavior: "smooth", top: 0 });
323
- if (typeof component === "string" && uiComponents.some((item) => item.id === component)) {
324
- return;
325
- }
326
- const firstComponent = uiComponents[0];
327
- if (!firstComponent) {
328
- return;
397
+
398
+ onMounted(() => {
399
+ colorSwatchesReady.value = true
400
+ })
401
+
402
+ watch(isNavigationOpen, async (isOpen) => {
403
+ if (isOpen) {
404
+ await nextTick()
405
+ mobileNavigation.value?.focus()
329
406
  }
330
- router.replace({
331
- path: "/ui",
332
- query: {
333
- ...route.query,
334
- component: firstComponent.id
407
+ })
408
+
409
+ watch(
410
+ () => route.query.component,
411
+ (component) => {
412
+ closeNavigation()
413
+ window.scrollTo({ behavior: 'smooth', top: 0 })
414
+ if (typeof component === 'string' && uiComponents.some((item) => item.id === component)) {
415
+ return
335
416
  }
336
- });
337
- },
338
- { immediate: true }
339
- );
340
- watch(
341
- () => activeComponent.value?.id,
342
- () => {
343
- stylesExpanded.value = false;
344
- }
345
- );
417
+
418
+ const firstComponent = uiComponents[0]
419
+ if (!firstComponent) {
420
+ return
421
+ }
422
+
423
+ router.replace({
424
+ path: '/ui',
425
+ query: {
426
+ ...route.query,
427
+ component: firstComponent.id,
428
+ },
429
+ })
430
+ },
431
+ { immediate: true },
432
+ )
433
+
434
+ watch(
435
+ () => activeComponent.value?.id,
436
+ () => {
437
+ stylesExpanded.value = false
438
+ },
439
+ )
346
440
  </script>
347
441
 
348
442
  <template>
@@ -423,18 +517,20 @@ watch(
423
517
  <NuxtLink
424
518
  v-for="component in uiComponents"
425
519
  :key="component.id"
426
- :aria-current="activeComponent?.id === component.id ? 'page' : void 0"
520
+ :aria-current="activeComponent?.id === component.id ? 'page' : undefined"
427
521
  :class="[
428
- 'block rounded-lg px-3 py-2.5 text-sm font-semibold tracking-wide transition',
429
- activeComponent?.id === component.id ? 'bg-blue-900 text-blue-100' : 'text-zinc-400 hover:bg-zinc-900 hover:text-zinc-100'
430
- ]"
522
+ 'block rounded-lg px-3 py-2.5 text-sm font-semibold tracking-wide transition',
523
+ activeComponent?.id === component.id
524
+ ? 'bg-blue-900 text-blue-100'
525
+ : 'text-zinc-400 hover:bg-zinc-900 hover:text-zinc-100',
526
+ ]"
431
527
  :to="{
432
- path: '/ui',
433
- query: {
434
- ...route.query,
435
- component: component.id
436
- }
437
- }"
528
+ path: '/ui',
529
+ query: {
530
+ ...route.query,
531
+ component: component.id,
532
+ },
533
+ }"
438
534
  @click="closeNavigation"
439
535
  >
440
536
  {{ component.name }}
@@ -454,18 +550,20 @@ watch(
454
550
  <NuxtLink
455
551
  v-for="component in uiComponents"
456
552
  :key="component.id"
457
- :aria-current="activeComponent?.id === component.id ? 'page' : void 0"
553
+ :aria-current="activeComponent?.id === component.id ? 'page' : undefined"
458
554
  :class="[
459
- 'block rounded-lg px-3 py-2 text-sm font-semibold tracking-wide transition',
460
- activeComponent?.id === component.id ? 'bg-blue-900 text-blue-100' : 'text-zinc-400 hover:bg-zinc-900 hover:text-zinc-100'
461
- ]"
555
+ 'block rounded-lg px-3 py-2 text-sm font-semibold tracking-wide transition',
556
+ activeComponent?.id === component.id
557
+ ? 'bg-blue-900 text-blue-100'
558
+ : 'text-zinc-400 hover:bg-zinc-900 hover:text-zinc-100',
559
+ ]"
462
560
  :to="{
463
- path: '/ui',
464
- query: {
465
- ...route.query,
466
- component: component.id
467
- }
468
- }"
561
+ path: '/ui',
562
+ query: {
563
+ ...route.query,
564
+ component: component.id,
565
+ },
566
+ }"
469
567
  >
470
568
  {{ component.name }}
471
569
  </NuxtLink>
@@ -540,9 +638,11 @@ watch(
540
638
  type="button"
541
639
  :aria-label="isDemoCodeExpanded(demo.id) ? 'Hide code' : 'View code'"
542
640
  :class="[
543
- 'flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md border transition focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-400',
544
- isDemoCodeExpanded(demo.id) ? 'border-blue-700 bg-blue-900 text-blue-200' : 'border-zinc-700 text-zinc-400 hover:border-blue-700 hover:text-blue-200'
545
- ]"
641
+ 'flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md border transition focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-400',
642
+ isDemoCodeExpanded(demo.id)
643
+ ? 'border-blue-700 bg-blue-900 text-blue-200'
644
+ : 'border-zinc-700 text-zinc-400 hover:border-blue-700 hover:text-blue-200',
645
+ ]"
546
646
  :title="isDemoCodeExpanded(demo.id) ? 'Hide code' : 'View code'"
547
647
  @click="toggleDemoCode(demo.id)"
548
648
  >
@@ -562,7 +662,7 @@ watch(
562
662
  </svg>
563
663
  </button>
564
664
  </header>
565
- <div class="p-8 mb:p-4">
665
+ <div class="overflow-auto p-8 mb:p-4">
566
666
  <component :is="demo.component" />
567
667
  </div>
568
668
  <div
@@ -615,7 +715,7 @@ watch(
615
715
  class="py-3 text-right text-xs"
616
716
  :class="prop.required ? 'text-red-600' : 'text-zinc-500'"
617
717
  >
618
- {{ prop.required ? "*" : "-" }}
718
+ {{ prop.required ? '*' : '-' }}
619
719
  </td>
620
720
  </tr>
621
721
  <tr v-if="activeComponent.props.length === 0">
@@ -700,7 +800,7 @@ watch(
700
800
  class="flex w-full cursor-pointer items-center justify-center text-sm font-medium text-cyan-500 transition hover:text-cyan-400 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cyan-400"
701
801
  @click="stylesExpanded = !stylesExpanded"
702
802
  >
703
- {{ stylesExpanded ? "Collapse styles" : `Show all ${activeComponent.styles.length} styles` }}
803
+ {{ stylesExpanded ? 'Collapse styles' : `Show all ${activeComponent.styles.length} styles` }}
704
804
  </button>
705
805
  </footer>
706
806
  </section>
@@ -721,10 +821,77 @@ watch(
721
821
  </main>
722
822
  </template>
723
823
 
724
- <style src="../ui-page.css">
725
-
726
- </style>
824
+ <style src="../ui-page.css"></style>
727
825
 
728
826
  <style module>
729
- :global(.ui-code-comment){color:var(--color-zinc-500,#71717a)}:global(.ui-code-string){color:var(--color-emerald-400,#34d399)}:global(.ui-code-keyword){color:var(--color-blue-400,#60a5fa)}:global(.ui-code-number){color:var(--color-amber-300,#fcd34d)}:global(.ui-code-tag){color:var(--color-cyan-500,#22d3ee)}:global(.ui-code-attribute){color:var(--color-violet-300,#c4b5fd)}:global(.ui-code-punctuation){color:var(--color-zinc-400,#a1a1aa)}:global(.ui-color-swatch){background:var(--ui-color-swatch);border:1px solid hsla(0,0%,100%,.1);border-radius:.2rem;display:inline-block;height:.65rem;margin-right:.25rem;opacity:.85;vertical-align:-.1rem;width:.65rem}.mobileNavigation{width:min(18rem,calc(100vw - 3rem))}@media (width >= 40rem){.styleGrid{grid-template-columns:minmax(12rem,.8fr) minmax(0,1.8fr)}}.styleValue :global(.ui-code-keyword){color:var(--color-zinc-500,#71717a)}.styleValue :global(.ui-code-attribute){color:var(--color-zinc-200,#e4e4e7)}.styleValue :global(.ui-code-string){color:var(--color-zinc-300,#d4d4d8)}.styleValue :global(.ui-code-number){color:var(--color-zinc-400,#a1a1aa)}.styleValue :global(.ui-code-punctuation){color:var(--color-zinc-500,#71717a)}
827
+ :global(.ui-code-comment) {
828
+ color: var(--color-zinc-500, #71717a);
829
+ }
830
+
831
+ :global(.ui-code-string) {
832
+ color: var(--color-emerald-400, #34d399);
833
+ }
834
+
835
+ :global(.ui-code-keyword) {
836
+ color: var(--color-blue-400, #60a5fa);
837
+ }
838
+
839
+ :global(.ui-code-number) {
840
+ color: var(--color-amber-300, #fcd34d);
841
+ }
842
+
843
+ :global(.ui-code-tag) {
844
+ color: var(--color-cyan-500, #22d3ee);
845
+ }
846
+
847
+ :global(.ui-code-attribute) {
848
+ color: var(--color-violet-300, #c4b5fd);
849
+ }
850
+
851
+ :global(.ui-code-punctuation) {
852
+ color: var(--color-zinc-400, #a1a1aa);
853
+ }
854
+
855
+ :global(.ui-color-swatch) {
856
+ display: inline-block;
857
+ width: 0.65rem;
858
+ height: 0.65rem;
859
+ margin-right: 0.25rem;
860
+ vertical-align: -0.1rem;
861
+ border: 1px solid rgb(255 255 255 / 10%);
862
+ border-radius: 0.2rem;
863
+ background: var(--ui-color-swatch);
864
+ opacity: 0.85;
865
+ /* box-shadow: inset 0 0 0 1px rgb(0 0 0 / 10%); */
866
+ }
867
+
868
+ .mobileNavigation {
869
+ width: min(18rem, calc(100vw - 3rem));
870
+ }
871
+
872
+ @media (width >= 40rem) {
873
+ .styleGrid {
874
+ grid-template-columns: minmax(12rem, 0.8fr) minmax(0, 1.8fr);
875
+ }
876
+ }
877
+
878
+ .styleValue :global(.ui-code-keyword) {
879
+ color: var(--color-zinc-500, #71717a);
880
+ }
881
+
882
+ .styleValue :global(.ui-code-attribute) {
883
+ color: var(--color-zinc-200, #e4e4e7);
884
+ }
885
+
886
+ .styleValue :global(.ui-code-string) {
887
+ color: var(--color-zinc-300, #d4d4d8);
888
+ }
889
+
890
+ .styleValue :global(.ui-code-number) {
891
+ color: var(--color-zinc-400, #a1a1aa);
892
+ }
893
+
894
+ .styleValue :global(.ui-code-punctuation) {
895
+ color: var(--color-zinc-500, #71717a);
896
+ }
730
897
  </style>