|
|
|
|
import { readFileSync, writeFileSync, readdirSync, existsSync } from 'fs';
|
|
|
|
|
import { join } from 'path';
|
|
|
|
|
|
|
|
|
|
const ICONS_SOURCE = join(process.cwd(), 'static/lucide/icons');
|
|
|
|
|
const ICONS_TARGET = join(process.cwd(), 'src/uix/air/icons/lib');
|
|
|
|
|
const INDEX_FILE = join(process.cwd(), 'src/uix/air/icons/sound.svelte.ts');
|
|
|
|
|
|
|
|
|
|
function getExistingIcons() {
|
|
|
|
|
const files = readdirSync(ICONS_TARGET);
|
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
return new Set(files.map((f) => f.replace('.svelte', '')));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function parseSvgContent(svgContent) {
|
|
|
|
|
// Extract all child elements (path, circle, rect, polyline, line, polygon, ellipse)
|
|
|
|
|
const elements = [];
|
|
|
|
|
|
|
|
|
|
const patterns = [
|
|
|
|
|
/<path\s+([^>]*)>/g,
|
|
|
|
|
/<circle\s+([^>]*)>/g,
|
|
|
|
|
/<rect\s+([^>]*)>/g,
|
|
|
|
|
/<polyline\s+([^>]*)>/g,
|
|
|
|
|
/<line\s+([^>]*)>/g,
|
|
|
|
|
/<polygon\s+([^>]*)>/g,
|
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
/<ellipse\s+([^>]*)>/g
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
for (const pattern of patterns) {
|
|
|
|
|
let match;
|
|
|
|
|
while ((match = pattern.exec(svgContent)) !== null) {
|
|
|
|
|
const tagName = pattern.source.replace('\\s+([^>]*)>', '').replace('<', '').replace('\\', '');
|
|
|
|
|
const attrs = match[1];
|
|
|
|
|
elements.push(`<${tagName} ${attrs}>`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return elements.join('\n\t');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toPascalCase(str) {
|
|
|
|
|
return str
|
|
|
|
|
.split(/[-_]/)
|
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
|
|
|
.join('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function convertIcon(iconName) {
|
|
|
|
|
const svgPath = join(ICONS_SOURCE, `${iconName}.svg`);
|
|
|
|
|
|
|
|
|
|
if (!existsSync(svgPath)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const svgContent = readFileSync(svgPath, 'utf-8');
|
|
|
|
|
const innerContent = parseSvgContent(svgContent);
|
|
|
|
|
|
|
|
|
|
// Generate Svelte component
|
|
|
|
|
const component = `<script lang="ts">
|
|
|
|
|
import Icon from '../icon.svelte';
|
|
|
|
|
import type { AirIconProps } from '../types';
|
|
|
|
|
|
|
|
|
|
let props: AirIconProps = $props();
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<Icon {...props}>
|
|
|
|
|
${innerContent}
|
|
|
|
|
</Icon>
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
return component;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateIndex(icons) {
|
|
|
|
|
const existingIndex = readFileSync(INDEX_FILE, 'utf-8');
|
|
|
|
|
const lines = existingIndex.split('\n');
|
|
|
|
|
|
|
|
|
|
// Find the last export line (before export type)
|
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
const lastExportLine = lines.findIndex((l) => l.startsWith('export type'));
|
|
|
|
|
|
|
|
|
|
// Collect existing exports
|
|
|
|
|
const existingExports = new Set();
|
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
lines.forEach((line) => {
|
|
|
|
|
const match = line.match(/export \{ default as (\w+) \}/);
|
|
|
|
|
if (match) existingExports.add(match[1]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Add new exports
|
|
|
|
|
const newExports = [];
|
|
|
|
|
for (const icon of icons) {
|
|
|
|
|
const pascalName = toPascalCase(icon);
|
|
|
|
|
if (!existingExports.has(pascalName)) {
|
|
|
|
|
newExports.push(`export { default as ${pascalName} } from './lib/${icon}.svelte';`);
|
|
|
|
|
existingExports.add(pascalName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (newExports.length === 0) return;
|
|
|
|
|
|
|
|
|
|
// Insert new exports before the export type line
|
|
|
|
|
lines.splice(lastExportLine, 0, ...newExports);
|
|
|
|
|
|
Add air components (toggle-group, toolbar, avatar, meter, collapsible), fix CSS audit issues, fix combobox scroll, rebuild documentation
Components:
- Add ToggleGroup air wrapper (surface/outline/ghost variants, 6 colors, sound)
- Add Toolbar air wrapper (Provider, Group, GroupItem, Button, Link + semantics)
- Add Avatar air wrapper (6 sizes, solid/soft/outline, 6 colors, 4 radii)
- Add Meter air wrapper (3 sizes, 6 colors, animated fill bar)
- Add Collapsible air wrapper (trigger, animated content, expansion semantics)
CSS audit fixes:
- Rename 65 public resolver vars to private (--_air-*) in checkbox, switch
- Fix button radius privatization and warning solid-fg
- Fix slider circular reference in default tokens
- Add disabled-opacity tokens to button, toggle, tabs, toggle-group
- Tokenize combobox chip styles (12 direct semantic refs → component tokens)
- Fix tabs stack-gap public override → private resolver
Bug fix:
- Fix combobox scroll-on-open: replace scrollIntoView() with viewport-scoped
scroll in select.svelte.ts to prevent page scroll when opening dropdown
Documentation rebuild (19 → 9 normative + 5 archived):
- Consolidate 15 air docs into 6 (README, ARCHITECTURE, TOKENS, VISUAL_LANGUAGE, SEMANTICS, IMPLEMENTATION_GUIDE)
- Archive 5 historical docs to _archive/
- Fix config/ → system/ references across terra and air docs
- Update component inventory (13 → 30 components)
- Fix font documentation (add Lora serif, update 12-step scale)
- Absorb SVELTE5_BINDABLE_PATTERN into terra README
- Update air hub page with all new component entries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
// Sort exports (keep TooltipContext first, then alphabetically)
|
|
|
|
|
const rootLine = lines[0];
|
|
|
|
|
const otherExports = lines.slice(1, lastExportLine + newExports.length);
|
|
|
|
|
const typeLine = lines[lastExportLine + newExports.length];
|
|
|
|
|
|
|
|
|
|
otherExports.sort();
|
|
|
|
|
|
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
const newContent = [
|
|
|
|
|
rootLine,
|
|
|
|
|
...otherExports,
|
|
|
|
|
typeLine,
|
|
|
|
|
...lines.slice(lastExportLine + newExports.length + 1)
|
|
|
|
|
].join('\n');
|
|
|
|
|
|
|
|
|
|
writeFileSync(INDEX_FILE, newContent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function main() {
|
|
|
|
|
const existingIcons = getExistingIcons();
|
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
const allSvgFiles = readdirSync(ICONS_SOURCE).filter((f) => f.endsWith('.svg'));
|
|
|
|
|
const missingIcons = allSvgFiles
|
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
.map((f) => f.replace('.svg', ''))
|
|
|
|
|
.filter((name) => !existingIcons.has(name));
|
|
|
|
|
|
|
|
|
|
console.log(`Found ${missingIcons.length} icons to convert...`);
|
|
|
|
|
|
|
|
|
|
if (missingIcons.length === 0) {
|
|
|
|
|
console.log('No new icons to convert!');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Limit to first 100 for testing
|
|
|
|
|
const toConvert = process.argv[2] === 'all' ? missingIcons : missingIcons.slice(0, 100);
|
|
|
|
|
|
|
|
|
|
console.log(`Converting ${toConvert.length} icons...`);
|
|
|
|
|
|
|
|
|
|
const converted = [];
|
|
|
|
|
|
|
|
|
|
for (const iconName of toConvert) {
|
|
|
|
|
const component = convertIcon(iconName);
|
|
|
|
|
if (component) {
|
|
|
|
|
const targetPath = join(ICONS_TARGET, `${iconName}.svelte`);
|
|
|
|
|
writeFileSync(targetPath, component);
|
|
|
|
|
converted.push(iconName);
|
|
|
|
|
console.log(`✓ ${iconName}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateIndex(converted);
|
|
|
|
|
console.log(`\nDone! Converted ${converted.length} icons.`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main();
|