@once-ui-system/core 1.7.11 → 1.7.13
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/AGENTS.md +53 -0
- package/README.md +27 -0
- package/agent/once-ui-codegen.mdc +27 -0
- package/ai/catalog.json +1650 -0
- package/ai/catalog.seed.json +411 -0
- package/ai/components/Accordion.json +136 -0
- package/ai/components/AccordionGroup.json +128 -0
- package/ai/components/Animation.json +146 -0
- package/ai/components/Arrow.json +128 -0
- package/ai/components/AutoScroll.json +130 -0
- package/ai/components/Avatar.json +133 -0
- package/ai/components/AvatarGroup.json +129 -0
- package/ai/components/Background.json +131 -0
- package/ai/components/Badge.json +132 -0
- package/ai/components/Banner.json +122 -0
- package/ai/components/BarChart.json +123 -0
- package/ai/components/BlobFx.json +125 -0
- package/ai/components/BlockQuote.json +132 -0
- package/ai/components/Button.json +26 -0
- package/ai/components/Card.json +129 -0
- package/ai/components/Carousel.json +134 -0
- package/ai/components/CelebrationFx.json +132 -0
- package/ai/components/ChartHeader.json +130 -0
- package/ai/components/ChartStatus.json +12 -0
- package/ai/components/Checkbox.json +13 -0
- package/ai/components/Chip.json +132 -0
- package/ai/components/CodeBlock.json +122 -0
- package/ai/components/ColorInput.json +13 -0
- package/ai/components/Column.json +128 -0
- package/ai/components/CompareImage.json +126 -0
- package/ai/components/ContextMenu.json +22 -0
- package/ai/components/CountFx.json +82 -0
- package/ai/components/CountdownFx.json +11 -0
- package/ai/components/Cursor.json +9 -0
- package/ai/components/CursorCard.json +128 -0
- package/ai/components/DataTooltip.json +15 -0
- package/ai/components/DateInput.json +21 -0
- package/ai/components/DatePicker.json +143 -0
- package/ai/components/DateRangeInput.json +18 -0
- package/ai/components/DateRangePicker.json +129 -0
- package/ai/components/Dialog.json +134 -0
- package/ai/components/DialogProvider.json +8 -0
- package/ai/components/Dropdown.json +128 -0
- package/ai/components/DropdownWrapper.json +28 -0
- package/ai/components/EmojiPicker.json +129 -0
- package/ai/components/EmojiPickerDropdown.json +13 -0
- package/ai/components/Fade.json +130 -0
- package/ai/components/FadingLettersFx.json +77 -0
- package/ai/components/Feedback.json +132 -0
- package/ai/components/Flex.json +125 -0
- package/ai/components/FlipFx.json +133 -0
- package/ai/components/GlitchFx.json +128 -0
- package/ai/components/Grid.json +121 -0
- package/ai/components/Heading.json +75 -0
- package/ai/components/HeadingLink.json +127 -0
- package/ai/components/HeadingNav.json +124 -0
- package/ai/components/HoloFx.json +128 -0
- package/ai/components/Hover.json +130 -0
- package/ai/components/HoverCard.json +122 -0
- package/ai/components/Icon.json +132 -0
- package/ai/components/IconButton.json +22 -0
- package/ai/components/InfiniteScroll.json +130 -0
- package/ai/components/InlineCode.json +126 -0
- package/ai/components/Input.json +24 -0
- package/ai/components/InteractiveDetails.json +14 -0
- package/ai/components/Kbar.json +10 -0
- package/ai/components/Kbd.json +127 -0
- package/ai/components/Legend.json +14 -0
- package/ai/components/LetterFx.json +14 -0
- package/ai/components/Line.json +125 -0
- package/ai/components/LineBarChart.json +123 -0
- package/ai/components/LineChart.json +123 -0
- package/ai/components/LinearGauge.json +130 -0
- package/ai/components/LinearGradient.json +15 -0
- package/ai/components/List.json +127 -0
- package/ai/components/ListItem.json +77 -0
- package/ai/components/Logo.json +16 -0
- package/ai/components/LogoCloud.json +124 -0
- package/ai/components/Mask.json +131 -0
- package/ai/components/MasonryGrid.json +132 -0
- package/ai/components/MatrixFx.json +135 -0
- package/ai/components/Media.json +142 -0
- package/ai/components/MediaUpload.json +122 -0
- package/ai/components/MegaMenu.json +125 -0
- package/ai/components/MobileMegaMenu.json +125 -0
- package/ai/components/Modal.json +12 -0
- package/ai/components/NavIcon.json +127 -0
- package/ai/components/NumberInput.json +16 -0
- package/ai/components/OTPInput.json +13 -0
- package/ai/components/OgCard.json +135 -0
- package/ai/components/Option.json +137 -0
- package/ai/components/Particle.json +135 -0
- package/ai/components/PasswordInput.json +8 -0
- package/ai/components/PieChart.json +123 -0
- package/ai/components/ProgressBar.json +131 -0
- package/ai/components/Pulse.json +129 -0
- package/ai/components/RadialGauge.json +134 -0
- package/ai/components/RadialGradient.json +16 -0
- package/ai/components/RadioButton.json +17 -0
- package/ai/components/RevealFx.json +131 -0
- package/ai/components/Row.json +128 -0
- package/ai/components/Schema.json +17 -0
- package/ai/components/ScrollContainer.json +126 -0
- package/ai/components/ScrollToTop.json +124 -0
- package/ai/components/Scroller.json +128 -0
- package/ai/components/SegmentedControl.json +132 -0
- package/ai/components/Select.json +21 -0
- package/ai/components/ShineFx.json +80 -0
- package/ai/components/Skeleton.json +129 -0
- package/ai/components/Slider.json +17 -0
- package/ai/components/SmartLink.json +17 -0
- package/ai/components/Spinner.json +127 -0
- package/ai/components/SplitView.json +129 -0
- package/ai/components/StatusIndicator.json +128 -0
- package/ai/components/StyleOverlay.json +126 -0
- package/ai/components/StylePanel.json +125 -0
- package/ai/components/Swiper.json +130 -0
- package/ai/components/Switch.json +20 -0
- package/ai/components/Table.json +140 -0
- package/ai/components/Tag.json +129 -0
- package/ai/components/TagInput.json +12 -0
- package/ai/components/Text.json +72 -0
- package/ai/components/Textarea.json +24 -0
- package/ai/components/ThemeSwitcher.json +122 -0
- package/ai/components/TiltFx.json +126 -0
- package/ai/components/Timeline.json +126 -0
- package/ai/components/Toast.json +13 -0
- package/ai/components/Toaster.json +14 -0
- package/ai/components/ToggleButton.json +24 -0
- package/ai/components/Tooltip.json +129 -0
- package/ai/components/TypeFx.json +15 -0
- package/ai/components/User.json +15 -0
- package/ai/components/UserMenu.json +16 -0
- package/ai/components/WeatherFx.json +133 -0
- package/ai/examples/auth.tsx +105 -0
- package/ai/examples/blocks/Background6.tsx +25 -0
- package/ai/examples/blocks/Chat1.tsx +70 -0
- package/ai/examples/blocks/Dashboard1.tsx +404 -0
- package/ai/examples/blocks/Feed3.tsx +151 -0
- package/ai/examples/blocks/Footer1.tsx +30 -0
- package/ai/examples/blocks/Footer2.tsx +96 -0
- package/ai/examples/blocks/Footer3.tsx +127 -0
- package/ai/examples/blocks/Footer4.tsx +406 -0
- package/ai/examples/blocks/Header1.tsx +370 -0
- package/ai/examples/blocks/Header2.tsx +98 -0
- package/ai/examples/blocks/Header3.tsx +133 -0
- package/ai/examples/blocks/Header4.tsx +123 -0
- package/ai/examples/blocks/Productivity1.tsx +318 -0
- package/ai/examples/blocks/Roadmap1.tsx +133 -0
- package/ai/examples/blocks/Sidebar1.tsx +34 -0
- package/ai/examples/blocks/Sidebar2.tsx +17 -0
- package/ai/examples/blocks/Sidebar4.tsx +92 -0
- package/ai/examples/blocks/Sidebar5.tsx +73 -0
- package/ai/examples/blocks/Streaming1.tsx +353 -0
- package/ai/examples/blocks/Table1.tsx +303 -0
- package/ai/examples/blocks/Waitlist1.tsx +141 -0
- package/ai/examples/blocks/content/chat1content.ts +65 -0
- package/ai/examples/blocks/content/resources.ts +5 -0
- package/ai/examples/blocks/content/roadmap1content.ts +51 -0
- package/ai/examples/blocks/manifest.json +191 -0
- package/ai/examples/dashboard.tsx +150 -0
- package/ai/examples/marketing-hero.tsx +152 -0
- package/ai/examples/pricing.tsx +219 -0
- package/ai/examples/settings.tsx +140 -0
- package/ai/gotchas.json +85 -0
- package/ai/manifest.json +21 -0
- package/ai/rules.compact.md +73 -0
- package/ai/spec.json +2694 -2701
- package/ai/tasks/auth.json +23 -0
- package/ai/tasks/chat.json +28 -0
- package/ai/tasks/dashboard.json +39 -0
- package/ai/tasks/index.json +12 -0
- package/ai/tasks/marketing-hero.json +38 -0
- package/ai/tasks/pricing.json +42 -0
- package/ai/tasks/roadmap.json +22 -0
- package/ai/tasks/settings.json +34 -0
- package/dist/AGENTS.md +53 -0
- package/dist/README.md +27 -0
- package/dist/agent/once-ui-codegen.mdc +27 -0
- package/dist/ai/catalog.json +1650 -0
- package/dist/ai/catalog.seed.json +411 -0
- package/dist/ai/components/Accordion.json +136 -0
- package/dist/ai/components/AccordionGroup.json +128 -0
- package/dist/ai/components/Animation.json +146 -0
- package/dist/ai/components/Arrow.json +128 -0
- package/dist/ai/components/AutoScroll.json +130 -0
- package/dist/ai/components/Avatar.json +133 -0
- package/dist/ai/components/AvatarGroup.json +129 -0
- package/dist/ai/components/Background.json +131 -0
- package/dist/ai/components/Badge.json +132 -0
- package/dist/ai/components/Banner.json +122 -0
- package/dist/ai/components/BarChart.json +123 -0
- package/dist/ai/components/BlobFx.json +125 -0
- package/dist/ai/components/BlockQuote.json +132 -0
- package/dist/ai/components/Button.json +26 -0
- package/dist/ai/components/Card.json +129 -0
- package/dist/ai/components/Carousel.json +134 -0
- package/dist/ai/components/CelebrationFx.json +132 -0
- package/dist/ai/components/ChartHeader.json +130 -0
- package/dist/ai/components/ChartStatus.json +12 -0
- package/dist/ai/components/Checkbox.json +13 -0
- package/dist/ai/components/Chip.json +132 -0
- package/dist/ai/components/CodeBlock.json +122 -0
- package/dist/ai/components/ColorInput.json +13 -0
- package/dist/ai/components/Column.json +128 -0
- package/dist/ai/components/CompareImage.json +126 -0
- package/dist/ai/components/ContextMenu.json +22 -0
- package/dist/ai/components/CountFx.json +82 -0
- package/dist/ai/components/CountdownFx.json +11 -0
- package/dist/ai/components/Cursor.json +9 -0
- package/dist/ai/components/CursorCard.json +128 -0
- package/dist/ai/components/DataTooltip.json +15 -0
- package/dist/ai/components/DateInput.json +21 -0
- package/dist/ai/components/DatePicker.json +143 -0
- package/dist/ai/components/DateRangeInput.json +18 -0
- package/dist/ai/components/DateRangePicker.json +129 -0
- package/dist/ai/components/Dialog.json +134 -0
- package/dist/ai/components/DialogProvider.json +8 -0
- package/dist/ai/components/Dropdown.json +128 -0
- package/dist/ai/components/DropdownWrapper.json +28 -0
- package/dist/ai/components/EmojiPicker.json +129 -0
- package/dist/ai/components/EmojiPickerDropdown.json +13 -0
- package/dist/ai/components/Fade.json +130 -0
- package/dist/ai/components/FadingLettersFx.json +77 -0
- package/dist/ai/components/Feedback.json +132 -0
- package/dist/ai/components/Flex.json +125 -0
- package/dist/ai/components/FlipFx.json +133 -0
- package/dist/ai/components/GlitchFx.json +128 -0
- package/dist/ai/components/Grid.json +121 -0
- package/dist/ai/components/Heading.json +75 -0
- package/dist/ai/components/HeadingLink.json +127 -0
- package/dist/ai/components/HeadingNav.json +124 -0
- package/dist/ai/components/HoloFx.json +128 -0
- package/dist/ai/components/Hover.json +130 -0
- package/dist/ai/components/HoverCard.json +122 -0
- package/dist/ai/components/Icon.json +132 -0
- package/dist/ai/components/IconButton.json +22 -0
- package/dist/ai/components/InfiniteScroll.json +130 -0
- package/dist/ai/components/InlineCode.json +126 -0
- package/dist/ai/components/Input.json +24 -0
- package/dist/ai/components/InteractiveDetails.json +14 -0
- package/dist/ai/components/Kbar.json +10 -0
- package/dist/ai/components/Kbd.json +127 -0
- package/dist/ai/components/Legend.json +14 -0
- package/dist/ai/components/LetterFx.json +14 -0
- package/dist/ai/components/Line.json +125 -0
- package/dist/ai/components/LineBarChart.json +123 -0
- package/dist/ai/components/LineChart.json +123 -0
- package/dist/ai/components/LinearGauge.json +130 -0
- package/dist/ai/components/LinearGradient.json +15 -0
- package/dist/ai/components/List.json +127 -0
- package/dist/ai/components/ListItem.json +77 -0
- package/dist/ai/components/Logo.json +16 -0
- package/dist/ai/components/LogoCloud.json +124 -0
- package/dist/ai/components/Mask.json +131 -0
- package/dist/ai/components/MasonryGrid.json +132 -0
- package/dist/ai/components/MatrixFx.json +135 -0
- package/dist/ai/components/Media.json +142 -0
- package/dist/ai/components/MediaUpload.json +122 -0
- package/dist/ai/components/MegaMenu.json +125 -0
- package/dist/ai/components/MobileMegaMenu.json +125 -0
- package/dist/ai/components/Modal.json +12 -0
- package/dist/ai/components/NavIcon.json +127 -0
- package/dist/ai/components/NumberInput.json +16 -0
- package/dist/ai/components/OTPInput.json +13 -0
- package/dist/ai/components/OgCard.json +135 -0
- package/dist/ai/components/Option.json +137 -0
- package/dist/ai/components/Particle.json +135 -0
- package/dist/ai/components/PasswordInput.json +8 -0
- package/dist/ai/components/PieChart.json +123 -0
- package/dist/ai/components/ProgressBar.json +131 -0
- package/dist/ai/components/Pulse.json +129 -0
- package/dist/ai/components/RadialGauge.json +134 -0
- package/dist/ai/components/RadialGradient.json +16 -0
- package/dist/ai/components/RadioButton.json +17 -0
- package/dist/ai/components/RevealFx.json +131 -0
- package/dist/ai/components/Row.json +128 -0
- package/dist/ai/components/Schema.json +17 -0
- package/dist/ai/components/ScrollContainer.json +126 -0
- package/dist/ai/components/ScrollToTop.json +124 -0
- package/dist/ai/components/Scroller.json +128 -0
- package/dist/ai/components/SegmentedControl.json +132 -0
- package/dist/ai/components/Select.json +21 -0
- package/dist/ai/components/ShineFx.json +80 -0
- package/dist/ai/components/Skeleton.json +129 -0
- package/dist/ai/components/Slider.json +17 -0
- package/dist/ai/components/SmartLink.json +17 -0
- package/dist/ai/components/Spinner.json +127 -0
- package/dist/ai/components/SplitView.json +129 -0
- package/dist/ai/components/StatusIndicator.json +128 -0
- package/dist/ai/components/StyleOverlay.json +126 -0
- package/dist/ai/components/StylePanel.json +125 -0
- package/dist/ai/components/Swiper.json +130 -0
- package/dist/ai/components/Switch.json +20 -0
- package/dist/ai/components/Table.json +140 -0
- package/dist/ai/components/Tag.json +129 -0
- package/dist/ai/components/TagInput.json +12 -0
- package/dist/ai/components/Text.json +72 -0
- package/dist/ai/components/Textarea.json +24 -0
- package/dist/ai/components/ThemeSwitcher.json +122 -0
- package/dist/ai/components/TiltFx.json +126 -0
- package/dist/ai/components/Timeline.json +126 -0
- package/dist/ai/components/Toast.json +13 -0
- package/dist/ai/components/Toaster.json +14 -0
- package/dist/ai/components/ToggleButton.json +24 -0
- package/dist/ai/components/Tooltip.json +129 -0
- package/dist/ai/components/TypeFx.json +15 -0
- package/dist/ai/components/User.json +15 -0
- package/dist/ai/components/UserMenu.json +16 -0
- package/dist/ai/components/WeatherFx.json +133 -0
- package/dist/ai/eval-tasks.md +71 -0
- package/dist/ai/examples/blocks/manifest.json +191 -0
- package/dist/ai/gotchas.json +85 -0
- package/dist/ai/manifest.json +21 -0
- package/dist/ai/recipes.md +149 -0
- package/dist/ai/rules.compact.md +73 -0
- package/dist/ai/rules.md +217 -0
- package/dist/ai/spec.json +2695 -0
- package/dist/ai/tasks/auth.json +23 -0
- package/dist/ai/tasks/chat.json +28 -0
- package/dist/ai/tasks/dashboard.json +39 -0
- package/dist/ai/tasks/index.json +12 -0
- package/dist/ai/tasks/marketing-hero.json +38 -0
- package/dist/ai/tasks/pricing.json +42 -0
- package/dist/ai/tasks/roadmap.json +22 -0
- package/dist/ai/tasks/settings.json +34 -0
- package/dist/components/ContextMenu.d.ts +2 -2
- package/dist/components/ContextMenu.d.ts.map +1 -1
- package/dist/components/ContextMenu.js +3 -3
- package/dist/components/ContextMenu.js.map +1 -1
- package/dist/components/ElementType.d.ts.map +1 -1
- package/dist/components/ElementType.js +6 -4
- package/dist/components/ElementType.js.map +1 -1
- package/dist/components/Media.d.ts.map +1 -1
- package/dist/components/Media.js +6 -3
- package/dist/components/Media.js.map +1 -1
- package/dist/components/MediaVideoPlayer.d.ts +12 -0
- package/dist/components/MediaVideoPlayer.d.ts.map +1 -0
- package/dist/components/MediaVideoPlayer.js +246 -0
- package/dist/components/MediaVideoPlayer.js.map +1 -0
- package/dist/components/MediaVideoPlayer.module.scss +90 -0
- package/dist/components/Table.d.ts +34 -6
- package/dist/components/Table.d.ts.map +1 -1
- package/dist/components/Table.js +114 -30
- package/dist/components/Table.js.map +1 -1
- package/dist/components/Table.module.scss +174 -3
- package/dist/components/ThemeInit.d.ts.map +1 -1
- package/dist/components/ThemeInit.js +2 -1
- package/dist/components/ThemeInit.js.map +1 -1
- package/dist/components/Timeline.d.ts +1 -1
- package/dist/components/Timeline.d.ts.map +1 -1
- package/dist/components/Timeline.js +16 -52
- package/dist/components/Timeline.js.map +1 -1
- package/dist/data/emoji-data.json +0 -10
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +7 -2
- package/dist/icons.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/code/CodeBlock.impl.d.ts.map +1 -1
- package/dist/modules/code/CodeBlock.impl.js +11 -5
- package/dist/modules/code/CodeBlock.impl.js.map +1 -1
- package/dist/modules/seo/Schema.d.ts.map +1 -1
- package/dist/modules/seo/Schema.js +3 -4
- package/dist/modules/seo/Schema.js.map +1 -1
- package/dist/package.json +33 -3
- package/dist/server/og-url-validation.d.ts +10 -0
- package/dist/server/og-url-validation.d.ts.map +1 -0
- package/dist/server/og-url-validation.js +234 -0
- package/dist/server/og-url-validation.js.map +1 -0
- package/dist/server/og-utils.d.ts +5 -2
- package/dist/server/og-utils.d.ts.map +1 -1
- package/dist/server/og-utils.js +39 -14
- package/dist/server/og-utils.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/safe-html.d.ts +19 -0
- package/dist/utils/safe-html.d.ts.map +1 -0
- package/dist/utils/safe-html.js +43 -0
- package/dist/utils/safe-html.js.map +1 -0
- package/package.json +159 -127
- package/scripts/copy-files.js +103 -0
- package/scripts/generate-ai-spec.js +464 -0
- package/scripts/generate-emoji-data.js +128 -0
- package/scripts/init-agent.js +156 -0
- package/scripts/validate-ai-code.js +149 -0
- package/LICENSE.md +0 -21
- package/next-env.d.ts +0 -5
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Scaffold agent harness pointers in a consumer project.
|
|
4
|
+
* Usage: npx once-ui-init-agent [--force] [--dry-run]
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
|
|
10
|
+
const PACKAGE_ROOT = path.join(__dirname, "..");
|
|
11
|
+
const MARKER_START = "<!-- once-ui-agent-harness:start -->";
|
|
12
|
+
const MARKER_END = "<!-- once-ui-agent-harness:end -->";
|
|
13
|
+
|
|
14
|
+
const PROJECT_AGENTS_SECTION = `${MARKER_START}
|
|
15
|
+
## Once UI codegen harness
|
|
16
|
+
|
|
17
|
+
Before generating Once UI code, load the harness from your installed package (not full doc pages):
|
|
18
|
+
|
|
19
|
+
1. Read \`node_modules/@once-ui-system/core/ai/manifest.json\`
|
|
20
|
+
2. Load bootstrap: \`ai/rules.compact.md\` + \`ai/catalog.json\`
|
|
21
|
+
3. Match intent via \`ai/tasks/index.json\` → fetch task bundle + component slices
|
|
22
|
+
4. Validate: \`npx once-ui-validate-ai-code path/to/file.tsx\`
|
|
23
|
+
|
|
24
|
+
npm exports: \`@once-ui-system/core/ai/manifest.json\`
|
|
25
|
+
|
|
26
|
+
Remote fallback: https://docs.once-ui.com/ai/manifest.json
|
|
27
|
+
${MARKER_END}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
function parseArgs(argv) {
|
|
31
|
+
return {
|
|
32
|
+
force: argv.includes("--force"),
|
|
33
|
+
dryRun: argv.includes("--dry-run"),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function findProjectRoot(startDir = process.cwd()) {
|
|
38
|
+
let dir = path.resolve(startDir);
|
|
39
|
+
|
|
40
|
+
while (true) {
|
|
41
|
+
const pkgPath = path.join(dir, "package.json");
|
|
42
|
+
if (fs.existsSync(pkgPath)) {
|
|
43
|
+
try {
|
|
44
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
45
|
+
if (pkg.name !== "@once-ui-system/core") {
|
|
46
|
+
return dir;
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
// keep walking
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const parent = path.dirname(dir);
|
|
54
|
+
if (parent === dir) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
dir = parent;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return path.resolve(startDir);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function upsertMarkedSection(existing, section, force) {
|
|
64
|
+
if (existing.includes(MARKER_START) && existing.includes(MARKER_END)) {
|
|
65
|
+
if (!force) {
|
|
66
|
+
return { content: existing, changed: false, reason: "AGENTS.md already contains Once UI harness section" };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const start = existing.indexOf(MARKER_START);
|
|
70
|
+
const end = existing.indexOf(MARKER_END) + MARKER_END.length;
|
|
71
|
+
return {
|
|
72
|
+
content: `${existing.slice(0, start)}${section}${existing.slice(end)}`,
|
|
73
|
+
changed: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (existing.trim().length === 0) {
|
|
78
|
+
return {
|
|
79
|
+
content: `# AGENTS.md\n\n${section}\n`,
|
|
80
|
+
changed: true,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
content: `${existing.trimEnd()}\n\n${section}\n`,
|
|
86
|
+
changed: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function writeFile(root, relativePath, content, { dryRun, force }) {
|
|
91
|
+
const target = path.join(root, relativePath);
|
|
92
|
+
const exists = fs.existsSync(target);
|
|
93
|
+
|
|
94
|
+
if (exists && !force) {
|
|
95
|
+
const current = fs.readFileSync(target, "utf8");
|
|
96
|
+
if (current === content) {
|
|
97
|
+
return { path: target, status: "unchanged" };
|
|
98
|
+
}
|
|
99
|
+
return { path: target, status: "skipped", reason: "already exists (use --force)" };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (dryRun) {
|
|
103
|
+
return { path: target, status: "would-write" };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
107
|
+
fs.writeFileSync(target, content, "utf8");
|
|
108
|
+
return { path: target, status: exists ? "updated" : "created" };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function main() {
|
|
112
|
+
const options = parseArgs(process.argv.slice(2));
|
|
113
|
+
const projectRoot = findProjectRoot();
|
|
114
|
+
const cursorRuleTemplate = fs.readFileSync(
|
|
115
|
+
path.join(PACKAGE_ROOT, "agent", "once-ui-codegen.mdc"),
|
|
116
|
+
"utf8",
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const agentsPath = path.join(projectRoot, "AGENTS.md");
|
|
120
|
+
let agentsContent = "";
|
|
121
|
+
if (fs.existsSync(agentsPath)) {
|
|
122
|
+
agentsContent = fs.readFileSync(agentsPath, "utf8");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const agentsResult = upsertMarkedSection(agentsContent, PROJECT_AGENTS_SECTION, options.force);
|
|
126
|
+
const results = [];
|
|
127
|
+
|
|
128
|
+
if (agentsResult.changed) {
|
|
129
|
+
results.push(
|
|
130
|
+
writeFile(projectRoot, "AGENTS.md", agentsResult.content, options),
|
|
131
|
+
);
|
|
132
|
+
} else {
|
|
133
|
+
results.push({
|
|
134
|
+
path: agentsPath,
|
|
135
|
+
status: "unchanged",
|
|
136
|
+
reason: agentsResult.reason,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
results.push(
|
|
141
|
+
writeFile(projectRoot, ".cursor/rules/once-ui-codegen.mdc", cursorRuleTemplate, options),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
console.log(`Once UI agent harness setup (${options.dryRun ? "dry run" : "applied"})`);
|
|
145
|
+
console.log(`Project root: ${projectRoot}`);
|
|
146
|
+
for (const result of results) {
|
|
147
|
+
const suffix = result.reason ? ` (${result.reason})` : "";
|
|
148
|
+
console.log(`- ${result.status}: ${path.relative(projectRoot, result.path)}${suffix}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!options.dryRun) {
|
|
152
|
+
console.log("\nNext: open a .tsx file and ask your agent to build Once UI — it should load the harness from node_modules/@once-ui-system/core/ai/");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
main();
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Mechanical Once UI codegen validator.
|
|
4
|
+
* Usage: node scripts/validate-ai-code.js <file.tsx> [--fix]
|
|
5
|
+
* node scripts/validate-ai-code.js --stdin < file.tsx
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
|
|
11
|
+
const ROOT = path.join(__dirname, "..");
|
|
12
|
+
const SPEC_PATH = path.join(ROOT, "ai", "spec.json");
|
|
13
|
+
|
|
14
|
+
function loadSpec() {
|
|
15
|
+
if (!fs.existsSync(SPEC_PATH)) return { components: {}, tokens: {} };
|
|
16
|
+
return JSON.parse(fs.readFileSync(SPEC_PATH, "utf8"));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function parseIconNames(spec) {
|
|
20
|
+
const raw = spec.tokens?.IconName || "";
|
|
21
|
+
const matches = raw.match(/"([^"]+)"/g) || [];
|
|
22
|
+
return new Set(matches.map((m) => m.slice(1, -1)));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function readInput(argv) {
|
|
26
|
+
const fileArg = argv.find((a) => !a.startsWith("-"));
|
|
27
|
+
if (argv.includes("--stdin")) {
|
|
28
|
+
return { source: fs.readFileSync(0, "utf8"), file: "<stdin>" };
|
|
29
|
+
}
|
|
30
|
+
if (!fileArg) {
|
|
31
|
+
console.error("Usage: validate-ai-code.js <file.tsx> [--fix] | --stdin");
|
|
32
|
+
process.exit(2);
|
|
33
|
+
}
|
|
34
|
+
return { source: fs.readFileSync(fileArg, "utf8"), file: fileArg };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function validate(source, spec, iconNames) {
|
|
38
|
+
const issues = [];
|
|
39
|
+
|
|
40
|
+
const add = (rule, message, fix) => issues.push({ rule, message, fix });
|
|
41
|
+
|
|
42
|
+
if (/fillWidth[\s\S]{0,80}fillHeight|<Flex[^>]*direction="column"|<Flex[^>]*direction="row"/.test(source)) {
|
|
43
|
+
if (/fillWidth[\s\S]{0,120}fillHeight/.test(source)) {
|
|
44
|
+
add("layout.shorthands", "Use fill instead of fillWidth + fillHeight", "fill");
|
|
45
|
+
}
|
|
46
|
+
if (/<Flex[^>]*direction="column"/.test(source)) {
|
|
47
|
+
add("layout.shorthands", "Use Column instead of Flex direction=\"column\"", "Column");
|
|
48
|
+
}
|
|
49
|
+
if (/<Flex[^>]*direction="row"/.test(source)) {
|
|
50
|
+
add("layout.shorthands", "Use Row instead of Flex direction=\"row\"", "Row");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (/horizontal="center"[\s\S]{0,80}vertical="center"/.test(source)) {
|
|
55
|
+
add("layout.shorthands", "Use center instead of horizontal=\"center\" vertical=\"center\"", "center");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (/position="relative"/.test(source)) {
|
|
59
|
+
add("layout.defaults", "position=\"relative\" is the default — omit it");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (/<Button[^>]*variant="primary"/.test(source)) {
|
|
63
|
+
add("layout.defaults", "variant=\"primary\" is the Button default — omit it");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (/#[0-9a-fA-F]{3,8}\b|rgb\s*\(|rgba\s*\(/.test(source)) {
|
|
67
|
+
add("color.tokens", "Use semantic color tokens, not hex/rgb");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (/<img[\s>/]|<a[\s>/]|<button[\s>/]/.test(source)) {
|
|
71
|
+
add("components.primitives", "Use Once UI components (Media, SmartLink, Button) instead of raw HTML");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const cardMatches = source.match(/<Card\b[^>]*>/g) || [];
|
|
75
|
+
for (const tag of cardMatches) {
|
|
76
|
+
if (!/\b(href|onClick)=/.test(tag)) {
|
|
77
|
+
add("Card.interactive", "Card without href/onClick — use Column + surface recipe for static panels");
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const iconPropRe = /(?:prefixIcon|suffixIcon|name)=["']([^"']+)["']/g;
|
|
83
|
+
let iconMatch;
|
|
84
|
+
while ((iconMatch = iconPropRe.exec(source)) !== null) {
|
|
85
|
+
const name = iconMatch[1];
|
|
86
|
+
if (iconNames.size && !iconNames.has(name)) {
|
|
87
|
+
add("Icon.names", `Unknown icon name "${name}" — use IconName from spec.json`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (/delay=\{[^}]*\*\s*80/.test(source)) {
|
|
92
|
+
add("RevealFx.delay", "RevealFx delay is in seconds — use index * 0.1, not index * 80");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (/<Fade[^>]*>[\s\S]*<(Column|Row)[^>]*overflowY/.test(source)) {
|
|
96
|
+
add("Fade.edge", "Fade wrapping scroll content — use as absolute edge strip instead");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (/style=\{\{[^}]*(gap|padding|margin|color|background):/.test(source)) {
|
|
100
|
+
add("spacing.tokens", "Use token props (gap, padding, background) instead of style={{}}");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return issues;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function applyFixes(source, issues) {
|
|
107
|
+
let out = source;
|
|
108
|
+
for (const issue of issues) {
|
|
109
|
+
if (issue.fix === "fill") {
|
|
110
|
+
out = out.replace(/\bfillWidth\b\s*\n?\s*\bfillHeight\b/g, "fill");
|
|
111
|
+
}
|
|
112
|
+
if (issue.fix === "center") {
|
|
113
|
+
out = out.replace(/\bhorizontal="center"\s*\n?\s*vertical="center"/g, "center");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function main() {
|
|
120
|
+
const spec = loadSpec();
|
|
121
|
+
const iconNames = parseIconNames(spec);
|
|
122
|
+
const fix = process.argv.includes("--fix");
|
|
123
|
+
const { source, file } = readInput(process.argv.slice(2));
|
|
124
|
+
|
|
125
|
+
const issues = validate(source, spec, iconNames);
|
|
126
|
+
|
|
127
|
+
if (issues.length === 0) {
|
|
128
|
+
console.log(`✓ ${file}: no mechanical issues`);
|
|
129
|
+
process.exit(0);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.log(`✗ ${file}: ${issues.length} issue(s)`);
|
|
133
|
+
for (const issue of issues) {
|
|
134
|
+
console.log(` [${issue.rule}] ${issue.message}`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (fix) {
|
|
138
|
+
const fixed = applyFixes(source, issues);
|
|
139
|
+
if (fixed !== source && !process.argv.includes("--stdin")) {
|
|
140
|
+
const fileArg = process.argv.find((a) => a.endsWith(".tsx") || a.endsWith(".jsx"));
|
|
141
|
+
fs.writeFileSync(fileArg, fixed);
|
|
142
|
+
console.log(`Applied auto-fixes to ${fileArg}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
main();
|
package/LICENSE.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024-2025 Once UI
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|