@c9up/nebula 0.1.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/LICENSE +21 -0
- package/README.md +256 -0
- package/dist/adapters/css.d.ts +33 -0
- package/dist/adapters/css.js +67 -0
- package/dist/adapters/index.d.ts +16 -0
- package/dist/adapters/index.js +27 -0
- package/dist/adapters/tailwind.d.ts +25 -0
- package/dist/adapters/tailwind.js +122 -0
- package/dist/adapters/types.d.ts +49 -0
- package/dist/adapters/types.js +21 -0
- package/dist/adapters/unocss.d.ts +17 -0
- package/dist/adapters/unocss.js +107 -0
- package/dist/atoms/AspectRatio.d.ts +17 -0
- package/dist/atoms/AspectRatio.js +19 -0
- package/dist/atoms/Avatar.d.ts +23 -0
- package/dist/atoms/Avatar.js +46 -0
- package/dist/atoms/Badge.d.ts +25 -0
- package/dist/atoms/Badge.js +28 -0
- package/dist/atoms/Button.d.ts +58 -0
- package/dist/atoms/Button.js +67 -0
- package/dist/atoms/Checkbox.d.ts +41 -0
- package/dist/atoms/Checkbox.js +47 -0
- package/dist/atoms/Input.d.ts +36 -0
- package/dist/atoms/Input.js +50 -0
- package/dist/atoms/Kbd.d.ts +14 -0
- package/dist/atoms/Kbd.js +17 -0
- package/dist/atoms/Label.d.ts +24 -0
- package/dist/atoms/Label.js +26 -0
- package/dist/atoms/Marker.d.ts +42 -0
- package/dist/atoms/Marker.js +55 -0
- package/dist/atoms/NativeSelect.d.ts +43 -0
- package/dist/atoms/NativeSelect.js +81 -0
- package/dist/atoms/Progress.d.ts +21 -0
- package/dist/atoms/Progress.js +48 -0
- package/dist/atoms/ScrollArea.d.ts +28 -0
- package/dist/atoms/ScrollArea.js +37 -0
- package/dist/atoms/Separator.d.ts +16 -0
- package/dist/atoms/Separator.js +21 -0
- package/dist/atoms/Skeleton.d.ts +13 -0
- package/dist/atoms/Skeleton.js +18 -0
- package/dist/atoms/Slider.d.ts +30 -0
- package/dist/atoms/Slider.js +40 -0
- package/dist/atoms/Spinner.d.ts +17 -0
- package/dist/atoms/Spinner.js +20 -0
- package/dist/atoms/Switch.d.ts +24 -0
- package/dist/atoms/Switch.js +41 -0
- package/dist/atoms/Textarea.d.ts +28 -0
- package/dist/atoms/Textarea.js +36 -0
- package/dist/atoms/Toggle.d.ts +38 -0
- package/dist/atoms/Toggle.js +45 -0
- package/dist/atoms/index.d.ts +32 -0
- package/dist/atoms/index.js +32 -0
- package/dist/cli/add.d.ts +44 -0
- package/dist/cli/add.js +99 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.js +10 -0
- package/dist/cli/registry.d.ts +31 -0
- package/dist/cli/registry.js +83 -0
- package/dist/config.d.ts +81 -0
- package/dist/config.js +43 -0
- package/dist/configure.d.ts +34 -0
- package/dist/configure.js +85 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +41 -0
- package/dist/lib/children.d.ts +28 -0
- package/dist/lib/children.js +27 -0
- package/dist/lib/cn.d.ts +13 -0
- package/dist/lib/cn.js +13 -0
- package/dist/lib/cva.d.ts +83 -0
- package/dist/lib/cva.js +178 -0
- package/dist/lib/icons.d.ts +44 -0
- package/dist/lib/icons.js +79 -0
- package/dist/lib/id.d.ts +31 -0
- package/dist/lib/id.js +41 -0
- package/dist/lib/index.d.ts +12 -0
- package/dist/lib/index.js +12 -0
- package/dist/lib/motion.d.ts +31 -0
- package/dist/lib/motion.js +39 -0
- package/dist/lib/props.d.ts +48 -0
- package/dist/lib/props.js +59 -0
- package/dist/lib/styled.d.ts +31 -0
- package/dist/lib/styled.js +39 -0
- package/dist/molecules/Accordion.d.ts +35 -0
- package/dist/molecules/Accordion.js +117 -0
- package/dist/molecules/Alert.d.ts +30 -0
- package/dist/molecules/Alert.js +35 -0
- package/dist/molecules/Attachment.d.ts +39 -0
- package/dist/molecules/Attachment.js +103 -0
- package/dist/molecules/Breadcrumb.d.ts +29 -0
- package/dist/molecules/Breadcrumb.js +73 -0
- package/dist/molecules/Bubble.d.ts +56 -0
- package/dist/molecules/Bubble.js +92 -0
- package/dist/molecules/ButtonGroup.d.ts +23 -0
- package/dist/molecules/ButtonGroup.js +30 -0
- package/dist/molecules/Card.d.ts +17 -0
- package/dist/molecules/Card.js +17 -0
- package/dist/molecules/Collapsible.d.ts +40 -0
- package/dist/molecules/Collapsible.js +71 -0
- package/dist/molecules/Empty.d.ts +16 -0
- package/dist/molecules/Empty.js +16 -0
- package/dist/molecules/Field.d.ts +54 -0
- package/dist/molecules/Field.js +82 -0
- package/dist/molecules/InputGroup.d.ts +33 -0
- package/dist/molecules/InputGroup.js +35 -0
- package/dist/molecules/InputOTP.d.ts +33 -0
- package/dist/molecules/InputOTP.js +140 -0
- package/dist/molecules/Item.d.ts +41 -0
- package/dist/molecules/Item.js +48 -0
- package/dist/molecules/Message.d.ts +43 -0
- package/dist/molecules/Message.js +82 -0
- package/dist/molecules/Pagination.d.ts +41 -0
- package/dist/molecules/Pagination.js +144 -0
- package/dist/molecules/RadioGroup.d.ts +32 -0
- package/dist/molecules/RadioGroup.js +65 -0
- package/dist/molecules/Resizable.d.ts +37 -0
- package/dist/molecules/Resizable.js +136 -0
- package/dist/molecules/Table.d.ts +37 -0
- package/dist/molecules/Table.js +78 -0
- package/dist/molecules/Tabs.d.ts +37 -0
- package/dist/molecules/Tabs.js +109 -0
- package/dist/molecules/ToggleGroup.d.ts +37 -0
- package/dist/molecules/ToggleGroup.js +68 -0
- package/dist/molecules/Typography.d.ts +26 -0
- package/dist/molecules/Typography.js +67 -0
- package/dist/molecules/index.d.ts +37 -0
- package/dist/molecules/index.js +37 -0
- package/dist/organisms/AlertDialog.d.ts +40 -0
- package/dist/organisms/AlertDialog.js +104 -0
- package/dist/organisms/Calendar.d.ts +96 -0
- package/dist/organisms/Calendar.js +353 -0
- package/dist/organisms/Carousel.d.ts +29 -0
- package/dist/organisms/Carousel.js +128 -0
- package/dist/organisms/Chart.d.ts +55 -0
- package/dist/organisms/Chart.js +189 -0
- package/dist/organisms/Combobox.d.ts +41 -0
- package/dist/organisms/Combobox.js +102 -0
- package/dist/organisms/Command.d.ts +46 -0
- package/dist/organisms/Command.js +171 -0
- package/dist/organisms/CommandDialog.d.ts +42 -0
- package/dist/organisms/CommandDialog.js +116 -0
- package/dist/organisms/ContextMenu.d.ts +29 -0
- package/dist/organisms/ContextMenu.js +102 -0
- package/dist/organisms/DataTable.d.ts +50 -0
- package/dist/organisms/DataTable.js +257 -0
- package/dist/organisms/DatePicker.d.ts +34 -0
- package/dist/organisms/DatePicker.js +115 -0
- package/dist/organisms/DateRangePicker.d.ts +34 -0
- package/dist/organisms/DateRangePicker.js +122 -0
- package/dist/organisms/Dialog.d.ts +50 -0
- package/dist/organisms/Dialog.js +116 -0
- package/dist/organisms/Drawer.d.ts +40 -0
- package/dist/organisms/Drawer.js +131 -0
- package/dist/organisms/DropdownMenu.d.ts +30 -0
- package/dist/organisms/DropdownMenu.js +91 -0
- package/dist/organisms/Form.d.ts +114 -0
- package/dist/organisms/Form.js +151 -0
- package/dist/organisms/HoverCard.d.ts +30 -0
- package/dist/organisms/HoverCard.js +68 -0
- package/dist/organisms/Menubar.d.ts +28 -0
- package/dist/organisms/Menubar.js +147 -0
- package/dist/organisms/MessageScroller.d.ts +36 -0
- package/dist/organisms/MessageScroller.js +124 -0
- package/dist/organisms/NavigationMenu.d.ts +41 -0
- package/dist/organisms/NavigationMenu.js +139 -0
- package/dist/organisms/Popover.d.ts +33 -0
- package/dist/organisms/Popover.js +58 -0
- package/dist/organisms/Questionnaire.d.ts +74 -0
- package/dist/organisms/Questionnaire.js +235 -0
- package/dist/organisms/Select.d.ts +47 -0
- package/dist/organisms/Select.js +250 -0
- package/dist/organisms/Sheet.d.ts +34 -0
- package/dist/organisms/Sheet.js +107 -0
- package/dist/organisms/Sidebar.d.ts +100 -0
- package/dist/organisms/Sidebar.js +228 -0
- package/dist/organisms/Toaster.d.ts +67 -0
- package/dist/organisms/Toaster.js +189 -0
- package/dist/organisms/Tooltip.d.ts +39 -0
- package/dist/organisms/Tooltip.js +94 -0
- package/dist/organisms/index.d.ts +40 -0
- package/dist/organisms/index.js +40 -0
- package/dist/primitives/controllable.d.ts +38 -0
- package/dist/primitives/controllable.js +43 -0
- package/dist/primitives/dismissable.d.ts +53 -0
- package/dist/primitives/dismissable.js +158 -0
- package/dist/primitives/floating.d.ts +116 -0
- package/dist/primitives/floating.js +289 -0
- package/dist/primitives/floatingSurface.d.ts +56 -0
- package/dist/primitives/floatingSurface.js +142 -0
- package/dist/primitives/focusTrap.d.ts +47 -0
- package/dist/primitives/focusTrap.js +101 -0
- package/dist/primitives/focusable.d.ts +53 -0
- package/dist/primitives/focusable.js +109 -0
- package/dist/primitives/index.d.ts +27 -0
- package/dist/primitives/index.js +27 -0
- package/dist/primitives/menu.d.ts +102 -0
- package/dist/primitives/menu.js +356 -0
- package/dist/primitives/modalSurface.d.ts +54 -0
- package/dist/primitives/modalSurface.js +146 -0
- package/dist/primitives/portal.d.ts +34 -0
- package/dist/primitives/portal.js +42 -0
- package/dist/primitives/presence.d.ts +45 -0
- package/dist/primitives/presence.js +152 -0
- package/dist/primitives/rovingFocus.d.ts +47 -0
- package/dist/primitives/rovingFocus.js +176 -0
- package/dist/primitives/scrollLock.d.ts +21 -0
- package/dist/primitives/scrollLock.js +75 -0
- package/dist/primitives/typeahead.d.ts +39 -0
- package/dist/primitives/typeahead.js +123 -0
- package/dist/templates/AppShell.d.ts +30 -0
- package/dist/templates/AppShell.js +42 -0
- package/dist/templates/AuthLayout.d.ts +23 -0
- package/dist/templates/AuthLayout.js +42 -0
- package/dist/templates/SettingsLayout.d.ts +27 -0
- package/dist/templates/SettingsLayout.js +42 -0
- package/dist/templates/index.d.ts +16 -0
- package/dist/templates/index.js +16 -0
- package/nebula.css +2 -0
- package/package.json +92 -0
- package/registry.json +1107 -0
- package/src/adapters/css.ts +75 -0
- package/src/adapters/index.ts +40 -0
- package/src/adapters/tailwind.ts +134 -0
- package/src/adapters/types.ts +53 -0
- package/src/adapters/unocss.ts +116 -0
- package/src/atoms/AspectRatio.ts +28 -0
- package/src/atoms/Avatar.ts +67 -0
- package/src/atoms/Badge.ts +46 -0
- package/src/atoms/Button.ts +96 -0
- package/src/atoms/Checkbox.ts +76 -0
- package/src/atoms/Input.ts +76 -0
- package/src/atoms/Kbd.ts +28 -0
- package/src/atoms/Label.ts +38 -0
- package/src/atoms/Marker.ts +79 -0
- package/src/atoms/NativeSelect.ts +115 -0
- package/src/atoms/Progress.ts +64 -0
- package/src/atoms/ScrollArea.ts +53 -0
- package/src/atoms/Separator.ts +36 -0
- package/src/atoms/Skeleton.ts +24 -0
- package/src/atoms/Slider.ts +65 -0
- package/src/atoms/Spinner.ts +28 -0
- package/src/atoms/Switch.ts +56 -0
- package/src/atoms/Textarea.ts +58 -0
- package/src/atoms/Toggle.ts +67 -0
- package/src/atoms/index.ts +62 -0
- package/src/cli/add.ts +126 -0
- package/src/cli/index.ts +22 -0
- package/src/cli/registry.ts +116 -0
- package/src/config.ts +102 -0
- package/src/configure.ts +127 -0
- package/src/index.ts +53 -0
- package/src/lib/children.ts +43 -0
- package/src/lib/cn.ts +14 -0
- package/src/lib/cva.ts +249 -0
- package/src/lib/icons.ts +138 -0
- package/src/lib/id.ts +44 -0
- package/src/lib/index.ts +21 -0
- package/src/lib/motion.ts +48 -0
- package/src/lib/props.ts +83 -0
- package/src/lib/styled.ts +60 -0
- package/src/molecules/Accordion.ts +161 -0
- package/src/molecules/Alert.ts +58 -0
- package/src/molecules/Attachment.ts +132 -0
- package/src/molecules/Breadcrumb.ts +107 -0
- package/src/molecules/Bubble.ts +134 -0
- package/src/molecules/ButtonGroup.ts +55 -0
- package/src/molecules/Card.ts +42 -0
- package/src/molecules/Collapsible.ts +89 -0
- package/src/molecules/Empty.ts +43 -0
- package/src/molecules/Field.ts +131 -0
- package/src/molecules/InputGroup.ts +62 -0
- package/src/molecules/InputOTP.ts +166 -0
- package/src/molecules/Item.ts +89 -0
- package/src/molecules/Message.ts +127 -0
- package/src/molecules/Pagination.ts +197 -0
- package/src/molecules/RadioGroup.ts +104 -0
- package/src/molecules/Resizable.ts +166 -0
- package/src/molecules/Table.ts +118 -0
- package/src/molecules/Tabs.ts +148 -0
- package/src/molecules/ToggleGroup.ts +109 -0
- package/src/molecules/Typography.ts +94 -0
- package/src/molecules/index.ts +144 -0
- package/src/organisms/AlertDialog.ts +133 -0
- package/src/organisms/Calendar.ts +470 -0
- package/src/organisms/Carousel.ts +161 -0
- package/src/organisms/Chart.ts +257 -0
- package/src/organisms/Combobox.ts +140 -0
- package/src/organisms/Command.ts +211 -0
- package/src/organisms/CommandDialog.ts +149 -0
- package/src/organisms/ContextMenu.ts +125 -0
- package/src/organisms/DataTable.ts +328 -0
- package/src/organisms/DatePicker.ts +141 -0
- package/src/organisms/DateRangePicker.ts +149 -0
- package/src/organisms/Dialog.ts +162 -0
- package/src/organisms/Drawer.ts +167 -0
- package/src/organisms/DropdownMenu.ts +112 -0
- package/src/organisms/Form.ts +217 -0
- package/src/organisms/HoverCard.ts +92 -0
- package/src/organisms/Menubar.ts +167 -0
- package/src/organisms/MessageScroller.ts +145 -0
- package/src/organisms/NavigationMenu.ts +184 -0
- package/src/organisms/Popover.ts +84 -0
- package/src/organisms/Questionnaire.ts +322 -0
- package/src/organisms/Select.ts +286 -0
- package/src/organisms/Sheet.ts +144 -0
- package/src/organisms/Sidebar.ts +336 -0
- package/src/organisms/Toaster.ts +246 -0
- package/src/organisms/Tooltip.ts +124 -0
- package/src/organisms/index.ts +134 -0
- package/src/primitives/controllable.ts +64 -0
- package/src/primitives/dismissable.ts +195 -0
- package/src/primitives/floating.ts +453 -0
- package/src/primitives/floatingSurface.ts +209 -0
- package/src/primitives/focusTrap.ts +132 -0
- package/src/primitives/focusable.ts +108 -0
- package/src/primitives/index.ts +88 -0
- package/src/primitives/menu.ts +491 -0
- package/src/primitives/modalSurface.ts +199 -0
- package/src/primitives/portal.ts +61 -0
- package/src/primitives/presence.ts +185 -0
- package/src/primitives/rovingFocus.ts +212 -0
- package/src/primitives/scrollLock.ts +79 -0
- package/src/primitives/typeahead.ts +156 -0
- package/src/templates/AppShell.ts +56 -0
- package/src/templates/AuthLayout.ts +66 -0
- package/src/templates/SettingsLayout.ts +63 -0
- package/src/templates/index.ts +21 -0
- package/theme.css +151 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ream configure @c9up/nebula` — the house setup hook.
|
|
3
|
+
*
|
|
4
|
+
* Every package in this workspace is installed the same way: `ream add <pkg>`
|
|
5
|
+
* installs it and dispatches to this hook, which writes the files the package
|
|
6
|
+
* needs through the codemods the CLI hands in. nebula follows that rather than
|
|
7
|
+
* shipping a setup command of its own — one way to install a ream package, not
|
|
8
|
+
* one per package.
|
|
9
|
+
*
|
|
10
|
+
* Pass the adapter through the installer:
|
|
11
|
+
*
|
|
12
|
+
* ream add @c9up/nebula --adapter unocss
|
|
13
|
+
*
|
|
14
|
+
* There is no provider to register. A provider binds runtime services into the
|
|
15
|
+
* container, and nebula has none: its components are client-side templates and
|
|
16
|
+
* its adapters run at build time. An empty provider would be ceremony.
|
|
17
|
+
*/
|
|
18
|
+
import { adapterFor, isAdapterName } from "./adapters/index.js";
|
|
19
|
+
import { resolveConfig } from "./config.js";
|
|
20
|
+
function configFile(adapter) {
|
|
21
|
+
return `import { defineConfig } from '@c9up/nebula'
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* nebula — component registry and style adapter.
|
|
25
|
+
*
|
|
26
|
+
* Changing \`adapter\` and re-running \`ream configure @c9up/nebula\` swaps the
|
|
27
|
+
* CSS engine. The components themselves are untouched: all three adapters
|
|
28
|
+
* consume the same class names.
|
|
29
|
+
*/
|
|
30
|
+
export default defineConfig({
|
|
31
|
+
adapter: '${adapter}',
|
|
32
|
+
paths: {
|
|
33
|
+
// Where \`ream nebula:add\` copies components. The atomic layers live under it.
|
|
34
|
+
components: 'resources/pages',
|
|
35
|
+
css: 'resources/css/app.css',
|
|
36
|
+
output: 'public/app.css',
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Read the adapter from the forwarded flags.
|
|
43
|
+
*
|
|
44
|
+
* An unrecognised name is refused rather than silently defaulted: a typo in
|
|
45
|
+
* `--adapter tailwnid` would otherwise write a Tailwind setup and leave the
|
|
46
|
+
* user hunting for why their UnoCSS config never appeared.
|
|
47
|
+
*/
|
|
48
|
+
function adapterFrom(flags) {
|
|
49
|
+
const requested = flags.adapter?.[0];
|
|
50
|
+
if (requested === undefined)
|
|
51
|
+
return "tailwind";
|
|
52
|
+
if (!isAdapterName(requested)) {
|
|
53
|
+
throw new Error(`[@c9up/nebula] unknown adapter "${requested}" — one of tailwind, unocss, css`);
|
|
54
|
+
}
|
|
55
|
+
return requested;
|
|
56
|
+
}
|
|
57
|
+
export async function configure(codemods, flags = {}) {
|
|
58
|
+
const name = adapterFrom(flags);
|
|
59
|
+
const adapter = adapterFor(name);
|
|
60
|
+
const config = resolveConfig({ adapter: name });
|
|
61
|
+
await codemods.writeFile("config/nebula.ts", configFile(name));
|
|
62
|
+
for (const file of adapter.files(config)) {
|
|
63
|
+
await codemods.writeFile(file.path, file.contents);
|
|
64
|
+
}
|
|
65
|
+
// On stderr, and never installed on the user's behalf. nebula declares no
|
|
66
|
+
// CSS dependency at all — the app owns its build tooling, and a UI library
|
|
67
|
+
// quietly adding one to someone's dependency tree is how a tree gets away
|
|
68
|
+
// from them.
|
|
69
|
+
const lines = [
|
|
70
|
+
"",
|
|
71
|
+
"[@c9up/nebula] configured with the " + name + " adapter.",
|
|
72
|
+
];
|
|
73
|
+
if (adapter.packages.length > 0) {
|
|
74
|
+
lines.push(" Install the engine yourself:", ` pnpm add -D ${adapter.packages.join(" ")}`);
|
|
75
|
+
}
|
|
76
|
+
const commands = adapter.commands(config);
|
|
77
|
+
if (commands === null) {
|
|
78
|
+
lines.push(" No build step — the stylesheet ships prebuilt.");
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
lines.push(" Register the build in config/assets.ts:", ` build: ${commands.build.command} ${commands.build.args.join(" ")}`, ` devServer: ${commands.dev.command} ${commands.dev.args.join(" ")}`);
|
|
82
|
+
}
|
|
83
|
+
lines.push(" Then add components with `ream nebula:add button card` — they are copied", " into your project and are yours to edit.", "");
|
|
84
|
+
process.stderr.write(lines.join("\n"));
|
|
85
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @c9up/nebula — shadcn/ui, ported to Aurora, organised as atomic design.
|
|
3
|
+
*
|
|
4
|
+
* Three things are worth knowing before reading further.
|
|
5
|
+
*
|
|
6
|
+
* **It adds no runtime dependency.** shadcn stands on Radix, `clsx`,
|
|
7
|
+
* `tailwind-merge`, `class-variance-authority`, `lucide-react`,
|
|
8
|
+
* `@floating-ui/dom`, `cmdk`, `sonner`, `recharts`, `@tanstack/react-table` and
|
|
9
|
+
* `react-day-picker`. None of them are React-agnostic, and the workspace had
|
|
10
|
+
* already made the call that `cn` was worth writing by hand rather than
|
|
11
|
+
* installing two packages. So `cva` is reimplemented, the Radix behaviour layer
|
|
12
|
+
* lives in `primitives/`, the placement engine is `primitives/floating.ts`, the
|
|
13
|
+
* icons are inlined, and the date maths is `Date` and `Intl`.
|
|
14
|
+
*
|
|
15
|
+
* **Compound components take data, not children.** shadcn composes through
|
|
16
|
+
* React context — `<Tabs><TabsList><TabsTrigger>`. Aurora has no context, and
|
|
17
|
+
* the workarounds are worse than the problem, so those components take an
|
|
18
|
+
* `items` array and named slots. The rendered markup is unchanged, which means
|
|
19
|
+
* shadcn's CSS and its examples still read across.
|
|
20
|
+
*
|
|
21
|
+
* **The atomic layer is a property of the component.** An atom renders its own
|
|
22
|
+
* markup and composes nothing from nebula; a molecule assembles atoms or owns
|
|
23
|
+
* state spanning several elements; an organism portals, traps focus, or floats;
|
|
24
|
+
* a template is page layout. `nebula add button` knows Button is an atom and
|
|
25
|
+
* puts it in `atoms/` without being told.
|
|
26
|
+
*
|
|
27
|
+
* Import from the layer barrels — `@c9up/nebula/atoms` — or take the source
|
|
28
|
+
* with `nebula add`, which is the mode this library is really built for.
|
|
29
|
+
*/
|
|
30
|
+
export * from "./adapters/index.js";
|
|
31
|
+
export * from "./atoms/index.js";
|
|
32
|
+
export { type AdapterName, defaultPaths, defineConfig, isLayer, type Layer, layers, type NebulaConfig, type NebulaPaths, type ResolvedNebulaConfig, resolveConfig, } from "./config.js";
|
|
33
|
+
export { type Child, type Slot, slot } from "./lib/children.js";
|
|
34
|
+
export * from "./lib/icons.js";
|
|
35
|
+
export * from "./lib/index.js";
|
|
36
|
+
export { fadeInOut, slideFrom, zoomInOut } from "./lib/motion.js";
|
|
37
|
+
export { type StyledProps, styledDiv, styledSpan } from "./lib/styled.js";
|
|
38
|
+
export * from "./molecules/index.js";
|
|
39
|
+
export * from "./organisms/index.js";
|
|
40
|
+
export * from "./primitives/index.js";
|
|
41
|
+
export * from "./templates/index.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @c9up/nebula — shadcn/ui, ported to Aurora, organised as atomic design.
|
|
3
|
+
*
|
|
4
|
+
* Three things are worth knowing before reading further.
|
|
5
|
+
*
|
|
6
|
+
* **It adds no runtime dependency.** shadcn stands on Radix, `clsx`,
|
|
7
|
+
* `tailwind-merge`, `class-variance-authority`, `lucide-react`,
|
|
8
|
+
* `@floating-ui/dom`, `cmdk`, `sonner`, `recharts`, `@tanstack/react-table` and
|
|
9
|
+
* `react-day-picker`. None of them are React-agnostic, and the workspace had
|
|
10
|
+
* already made the call that `cn` was worth writing by hand rather than
|
|
11
|
+
* installing two packages. So `cva` is reimplemented, the Radix behaviour layer
|
|
12
|
+
* lives in `primitives/`, the placement engine is `primitives/floating.ts`, the
|
|
13
|
+
* icons are inlined, and the date maths is `Date` and `Intl`.
|
|
14
|
+
*
|
|
15
|
+
* **Compound components take data, not children.** shadcn composes through
|
|
16
|
+
* React context — `<Tabs><TabsList><TabsTrigger>`. Aurora has no context, and
|
|
17
|
+
* the workarounds are worse than the problem, so those components take an
|
|
18
|
+
* `items` array and named slots. The rendered markup is unchanged, which means
|
|
19
|
+
* shadcn's CSS and its examples still read across.
|
|
20
|
+
*
|
|
21
|
+
* **The atomic layer is a property of the component.** An atom renders its own
|
|
22
|
+
* markup and composes nothing from nebula; a molecule assembles atoms or owns
|
|
23
|
+
* state spanning several elements; an organism portals, traps focus, or floats;
|
|
24
|
+
* a template is page layout. `nebula add button` knows Button is an atom and
|
|
25
|
+
* puts it in `atoms/` without being told.
|
|
26
|
+
*
|
|
27
|
+
* Import from the layer barrels — `@c9up/nebula/atoms` — or take the source
|
|
28
|
+
* with `nebula add`, which is the mode this library is really built for.
|
|
29
|
+
*/
|
|
30
|
+
export * from "./adapters/index.js";
|
|
31
|
+
export * from "./atoms/index.js";
|
|
32
|
+
export { defaultPaths, defineConfig, isLayer, layers, resolveConfig, } from "./config.js";
|
|
33
|
+
export { slot } from "./lib/children.js";
|
|
34
|
+
export * from "./lib/icons.js";
|
|
35
|
+
export * from "./lib/index.js";
|
|
36
|
+
export { fadeInOut, slideFrom, zoomInOut } from "./lib/motion.js";
|
|
37
|
+
export { styledDiv, styledSpan } from "./lib/styled.js";
|
|
38
|
+
export * from "./molecules/index.js";
|
|
39
|
+
export * from "./organisms/index.js";
|
|
40
|
+
export * from "./primitives/index.js";
|
|
41
|
+
export * from "./templates/index.js";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a component accepts as content.
|
|
3
|
+
*
|
|
4
|
+
* Aurora's renderer already handles the whole union in a text slot: nested
|
|
5
|
+
* templates, raw nodes, primitives, and arrays of any of those, with `null`,
|
|
6
|
+
* `undefined` and `false` rendering nothing. `Child` names that union so a
|
|
7
|
+
* component's props say what they mean instead of falling back to `unknown`,
|
|
8
|
+
* and so passing a value the renderer would silently drop is a type error at
|
|
9
|
+
* the call site rather than a blank space on the page.
|
|
10
|
+
*
|
|
11
|
+
* `Slot` is the reactive form. Content that changes must arrive as an accessor
|
|
12
|
+
* — Aurora never re-renders a component, so a plain value read at setup is
|
|
13
|
+
* frozen for the lifetime of the node.
|
|
14
|
+
*/
|
|
15
|
+
import type { TemplateResult } from "@c9up/aurora";
|
|
16
|
+
import type { Reactive } from "./props.js";
|
|
17
|
+
export type Child = TemplateResult | Node | string | number | boolean | null | undefined | readonly Child[];
|
|
18
|
+
/** Content that may be constant or recomputed. */
|
|
19
|
+
export type Slot = Reactive<Child>;
|
|
20
|
+
/**
|
|
21
|
+
* Bind content into a template so it stays live.
|
|
22
|
+
*
|
|
23
|
+
* Returns the accessor form unchanged and wraps a constant in one. Templates
|
|
24
|
+
* should always interpolate `${slot(props.children)}`: handing the renderer a
|
|
25
|
+
* bare value works until a sibling prop makes the content dynamic, at which
|
|
26
|
+
* point the binding quietly stops updating and nothing points at why.
|
|
27
|
+
*/
|
|
28
|
+
export declare function slot(content: Slot | undefined): () => Child;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a component accepts as content.
|
|
3
|
+
*
|
|
4
|
+
* Aurora's renderer already handles the whole union in a text slot: nested
|
|
5
|
+
* templates, raw nodes, primitives, and arrays of any of those, with `null`,
|
|
6
|
+
* `undefined` and `false` rendering nothing. `Child` names that union so a
|
|
7
|
+
* component's props say what they mean instead of falling back to `unknown`,
|
|
8
|
+
* and so passing a value the renderer would silently drop is a type error at
|
|
9
|
+
* the call site rather than a blank space on the page.
|
|
10
|
+
*
|
|
11
|
+
* `Slot` is the reactive form. Content that changes must arrive as an accessor
|
|
12
|
+
* — Aurora never re-renders a component, so a plain value read at setup is
|
|
13
|
+
* frozen for the lifetime of the node.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Bind content into a template so it stays live.
|
|
17
|
+
*
|
|
18
|
+
* Returns the accessor form unchanged and wraps a constant in one. Templates
|
|
19
|
+
* should always interpolate `${slot(props.children)}`: handing the renderer a
|
|
20
|
+
* bare value works until a sibling prop makes the content dynamic, at which
|
|
21
|
+
* point the binding quietly stops updating and nothing points at why.
|
|
22
|
+
*/
|
|
23
|
+
export function slot(content) {
|
|
24
|
+
if (content === undefined)
|
|
25
|
+
return () => null;
|
|
26
|
+
return typeof content === "function" ? content : () => content;
|
|
27
|
+
}
|
package/dist/lib/cn.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class composition — re-exported from Aurora rather than reimplemented here.
|
|
3
|
+
*
|
|
4
|
+
* `@c9up/aurora` already ships `clsx` + `tailwind-merge` written from scratch
|
|
5
|
+
* with no dependencies (its `src/cn.ts`, targeting the Tailwind v4 utility
|
|
6
|
+
* set). nebula is a peer of aurora, never a fork of it: one class-merge
|
|
7
|
+
* implementation in the workspace, one place to fix a mis-grouped utility.
|
|
8
|
+
*
|
|
9
|
+
* This module exists so every nebula component imports `./lib/cn.js` and not
|
|
10
|
+
* `@c9up/aurora` directly. That indirection is what lets the registry rewrite
|
|
11
|
+
* a single import line when it copies a component into a host app.
|
|
12
|
+
*/
|
|
13
|
+
export { type ClassValue, clsx, cn, twMerge } from "@c9up/aurora";
|
package/dist/lib/cn.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class composition — re-exported from Aurora rather than reimplemented here.
|
|
3
|
+
*
|
|
4
|
+
* `@c9up/aurora` already ships `clsx` + `tailwind-merge` written from scratch
|
|
5
|
+
* with no dependencies (its `src/cn.ts`, targeting the Tailwind v4 utility
|
|
6
|
+
* set). nebula is a peer of aurora, never a fork of it: one class-merge
|
|
7
|
+
* implementation in the workspace, one place to fix a mis-grouped utility.
|
|
8
|
+
*
|
|
9
|
+
* This module exists so every nebula component imports `./lib/cn.js` and not
|
|
10
|
+
* `@c9up/aurora` directly. That indirection is what lets the registry rewrite
|
|
11
|
+
* a single import line when it copies a component into a host app.
|
|
12
|
+
*/
|
|
13
|
+
export { clsx, cn, twMerge } from "@c9up/aurora";
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cva` — class-variance-authority, reimplemented from scratch with ZERO
|
|
3
|
+
* dependencies.
|
|
4
|
+
*
|
|
5
|
+
* shadcn/ui is built on two class helpers: `cn` (clsx + tailwind-merge) and
|
|
6
|
+
* `cva` (variant → class-list resolution). Aurora already ships `cn` written
|
|
7
|
+
* from scratch in `@c9up/aurora` (src/cn.ts), so this file is the other half.
|
|
8
|
+
* Between them, nebula pulls in no runtime dependency at all.
|
|
9
|
+
*
|
|
10
|
+
* const button = cva(
|
|
11
|
+
* "inline-flex items-center rounded-md text-sm font-medium",
|
|
12
|
+
* {
|
|
13
|
+
* variants: {
|
|
14
|
+
* variant: { default: "bg-primary text-primary-foreground",
|
|
15
|
+
* ghost: "hover:bg-accent" },
|
|
16
|
+
* size: { sm: "h-8 px-3", lg: "h-10 px-8" },
|
|
17
|
+
* },
|
|
18
|
+
* compoundVariants: [
|
|
19
|
+
* { variant: "ghost", size: "sm", class: "px-2" },
|
|
20
|
+
* ],
|
|
21
|
+
* defaultVariants: { variant: "default", size: "sm" },
|
|
22
|
+
* },
|
|
23
|
+
* )
|
|
24
|
+
*
|
|
25
|
+
* button() // base + default variants
|
|
26
|
+
* button({ variant: "ghost" }) // ghost, still size sm
|
|
27
|
+
* button({ size: "lg", class: "w-full" }) // caller classes win
|
|
28
|
+
*
|
|
29
|
+
* Differences from the upstream package, both deliberate:
|
|
30
|
+
*
|
|
31
|
+
* 1. The result runs through Aurora's `cn`, so a variant that sets `px-2`
|
|
32
|
+
* genuinely overrides a base `px-3` instead of emitting both and leaving
|
|
33
|
+
* the winner to CSS source order. Upstream cva only concatenates; every
|
|
34
|
+
* real shadcn component then wraps the call in `cn(...)` to get here
|
|
35
|
+
* anyway. Doing it inside removes that ceremony from ~50 components.
|
|
36
|
+
* 2. `class` and `className` are both accepted. Aurora templates use `class`;
|
|
37
|
+
* `className` exists only so code pasted over from a React codebase keeps
|
|
38
|
+
* working.
|
|
39
|
+
*/
|
|
40
|
+
import { type ClassValue } from "./cn.js";
|
|
41
|
+
/**
|
|
42
|
+
* One variant axis: a variant name mapped to the classes each of its values
|
|
43
|
+
* contributes. `{ size: { sm: "h-8", lg: "h-10" } }` is one axis with two
|
|
44
|
+
* values.
|
|
45
|
+
*/
|
|
46
|
+
export type VariantShape = Record<string, Record<string, ClassValue>>;
|
|
47
|
+
/**
|
|
48
|
+
* The value accepted for one axis.
|
|
49
|
+
*
|
|
50
|
+
* An axis keyed by `"true"` / `"false"` is a boolean axis — the caller passes
|
|
51
|
+
* a real `boolean`, not the string. That mapping is what lets
|
|
52
|
+
* `{ disabled: { true: "opacity-50" } }` be driven by `disabled: true`.
|
|
53
|
+
*/
|
|
54
|
+
type VariantValue<T> = Extract<keyof T, string> extends "true" | "false" ? boolean : Extract<keyof T, string>;
|
|
55
|
+
/** Props selecting one value per axis. Every axis is optional. */
|
|
56
|
+
export type VariantSelection<V extends VariantShape> = {
|
|
57
|
+
[K in keyof V]?: VariantValue<V[K]> | null | undefined;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* A compound rule matches when EVERY axis it names matches. An axis may list
|
|
61
|
+
* several accepted values, in which case any of them matches.
|
|
62
|
+
*/
|
|
63
|
+
export type CompoundVariant<V extends VariantShape> = {
|
|
64
|
+
[K in keyof V]?: VariantValue<V[K]> | ReadonlyArray<VariantValue<V[K]>>;
|
|
65
|
+
} & ClassOverrides;
|
|
66
|
+
/** Extra keys every generated function accepts on top of its own axes. */
|
|
67
|
+
export interface ClassOverrides {
|
|
68
|
+
class?: ClassValue;
|
|
69
|
+
className?: ClassValue;
|
|
70
|
+
}
|
|
71
|
+
export interface VariantConfig<V extends VariantShape> {
|
|
72
|
+
variants?: V;
|
|
73
|
+
compoundVariants?: ReadonlyArray<CompoundVariant<V>>;
|
|
74
|
+
defaultVariants?: VariantSelection<V>;
|
|
75
|
+
}
|
|
76
|
+
/** The props a `cva()` result accepts, minus the two class escape hatches. */
|
|
77
|
+
export type VariantProps<F> = F extends (props?: infer P) => string ? Omit<NonNullable<P>, "class" | "className"> : never;
|
|
78
|
+
/**
|
|
79
|
+
* Build a variant resolver. Returns a function from a variant selection to a
|
|
80
|
+
* single, conflict-resolved class string.
|
|
81
|
+
*/
|
|
82
|
+
export declare function cva<V extends VariantShape>(base?: ClassValue, config?: VariantConfig<V>): (props?: VariantSelection<V> & ClassOverrides) => string;
|
|
83
|
+
export {};
|
package/dist/lib/cva.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cva` — class-variance-authority, reimplemented from scratch with ZERO
|
|
3
|
+
* dependencies.
|
|
4
|
+
*
|
|
5
|
+
* shadcn/ui is built on two class helpers: `cn` (clsx + tailwind-merge) and
|
|
6
|
+
* `cva` (variant → class-list resolution). Aurora already ships `cn` written
|
|
7
|
+
* from scratch in `@c9up/aurora` (src/cn.ts), so this file is the other half.
|
|
8
|
+
* Between them, nebula pulls in no runtime dependency at all.
|
|
9
|
+
*
|
|
10
|
+
* const button = cva(
|
|
11
|
+
* "inline-flex items-center rounded-md text-sm font-medium",
|
|
12
|
+
* {
|
|
13
|
+
* variants: {
|
|
14
|
+
* variant: { default: "bg-primary text-primary-foreground",
|
|
15
|
+
* ghost: "hover:bg-accent" },
|
|
16
|
+
* size: { sm: "h-8 px-3", lg: "h-10 px-8" },
|
|
17
|
+
* },
|
|
18
|
+
* compoundVariants: [
|
|
19
|
+
* { variant: "ghost", size: "sm", class: "px-2" },
|
|
20
|
+
* ],
|
|
21
|
+
* defaultVariants: { variant: "default", size: "sm" },
|
|
22
|
+
* },
|
|
23
|
+
* )
|
|
24
|
+
*
|
|
25
|
+
* button() // base + default variants
|
|
26
|
+
* button({ variant: "ghost" }) // ghost, still size sm
|
|
27
|
+
* button({ size: "lg", class: "w-full" }) // caller classes win
|
|
28
|
+
*
|
|
29
|
+
* Differences from the upstream package, both deliberate:
|
|
30
|
+
*
|
|
31
|
+
* 1. The result runs through Aurora's `cn`, so a variant that sets `px-2`
|
|
32
|
+
* genuinely overrides a base `px-3` instead of emitting both and leaving
|
|
33
|
+
* the winner to CSS source order. Upstream cva only concatenates; every
|
|
34
|
+
* real shadcn component then wraps the call in `cn(...)` to get here
|
|
35
|
+
* anyway. Doing it inside removes that ceremony from ~50 components.
|
|
36
|
+
* 2. `class` and `className` are both accepted. Aurora templates use `class`;
|
|
37
|
+
* `className` exists only so code pasted over from a React codebase keeps
|
|
38
|
+
* working.
|
|
39
|
+
*/
|
|
40
|
+
import { cn } from "./cn.js";
|
|
41
|
+
/**
|
|
42
|
+
* Build a variant resolver. Returns a function from a variant selection to a
|
|
43
|
+
* single, conflict-resolved class string.
|
|
44
|
+
*/
|
|
45
|
+
export function cva(base, config) {
|
|
46
|
+
// Widening to the non-generic shapes up front is what keeps the body free
|
|
47
|
+
// of casts: `V` cannot be indexed by a plain `string`, `VariantShape` can.
|
|
48
|
+
const variants = config?.variants ?? {};
|
|
49
|
+
const axes = Object.keys(variants);
|
|
50
|
+
const defaults = toValueMap(config?.defaultVariants);
|
|
51
|
+
const compounds = normaliseCompounds(config?.compoundVariants);
|
|
52
|
+
return (props) => {
|
|
53
|
+
const selection = selectionFor(defaults, props);
|
|
54
|
+
const parts = [base];
|
|
55
|
+
for (const axis of axes) {
|
|
56
|
+
const chosen = selection[axis];
|
|
57
|
+
if (chosen === undefined)
|
|
58
|
+
continue;
|
|
59
|
+
// Indexed by the *string form* of the value, so a boolean axis reaches
|
|
60
|
+
// its `"true"` / `"false"` entry here.
|
|
61
|
+
const classesForValue = variants[axis]?.[chosen];
|
|
62
|
+
if (classesForValue !== undefined)
|
|
63
|
+
parts.push(classesForValue);
|
|
64
|
+
}
|
|
65
|
+
for (const rule of compounds) {
|
|
66
|
+
if (satisfies(rule, selection))
|
|
67
|
+
parts.push(...rule.classes);
|
|
68
|
+
}
|
|
69
|
+
// Caller overrides come last so they win the tailwind-merge pass.
|
|
70
|
+
parts.push(props?.class, props?.className);
|
|
71
|
+
return cn(parts);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Read an object's own enumerable entries with honest `unknown` values.
|
|
76
|
+
*
|
|
77
|
+
* Variant selections are generic mapped types, which TypeScript will not let
|
|
78
|
+
* you index with a plain `string`. Funnelling every read through one helper
|
|
79
|
+
* typed `object → [string, unknown][]` gets the values out without a cast at
|
|
80
|
+
* any call site, and forces each one to narrow before use.
|
|
81
|
+
*/
|
|
82
|
+
function entriesOf(source) {
|
|
83
|
+
return Object.entries(source);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Collapse a selection object down to `axis → string value`.
|
|
87
|
+
*
|
|
88
|
+
* Normalising to strings here is what keeps boolean-axis handling in a single
|
|
89
|
+
* place: `true` becomes `"true"`, and every lookup downstream — variant
|
|
90
|
+
* classes and compound matching alike — is a plain string compare.
|
|
91
|
+
*/
|
|
92
|
+
function toValueMap(source) {
|
|
93
|
+
const out = {};
|
|
94
|
+
if (!source)
|
|
95
|
+
return out;
|
|
96
|
+
for (const [key, value] of entriesOf(source)) {
|
|
97
|
+
if (isClassKey(key))
|
|
98
|
+
continue;
|
|
99
|
+
if (value === undefined || value === null)
|
|
100
|
+
continue;
|
|
101
|
+
out[key] = String(value);
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Merge caller props over the defaults.
|
|
107
|
+
*
|
|
108
|
+
* An omitted axis (or an explicit `undefined`) keeps its default; an explicit
|
|
109
|
+
* `null` clears it, which is how upstream cva lets a caller opt out of a
|
|
110
|
+
* default variant entirely.
|
|
111
|
+
*/
|
|
112
|
+
function selectionFor(defaults, props) {
|
|
113
|
+
const selection = { ...defaults };
|
|
114
|
+
if (!props)
|
|
115
|
+
return selection;
|
|
116
|
+
for (const [key, value] of entriesOf(props)) {
|
|
117
|
+
if (isClassKey(key))
|
|
118
|
+
continue;
|
|
119
|
+
if (value === undefined)
|
|
120
|
+
continue;
|
|
121
|
+
selection[key] = value === null ? undefined : String(value);
|
|
122
|
+
}
|
|
123
|
+
return selection;
|
|
124
|
+
}
|
|
125
|
+
/** Flatten compound rules once, at construction, rather than on every call. */
|
|
126
|
+
function normaliseCompounds(compounds) {
|
|
127
|
+
if (!compounds)
|
|
128
|
+
return [];
|
|
129
|
+
const out = [];
|
|
130
|
+
for (const rule of compounds) {
|
|
131
|
+
const conditions = [];
|
|
132
|
+
const classes = [];
|
|
133
|
+
for (const [key, value] of entriesOf(rule)) {
|
|
134
|
+
if (isClassKey(key)) {
|
|
135
|
+
if (isClassValue(value))
|
|
136
|
+
classes.push(value);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (value === undefined || value === null)
|
|
140
|
+
continue;
|
|
141
|
+
const accepted = Array.isArray(value)
|
|
142
|
+
? value.map((one) => String(one))
|
|
143
|
+
: [String(value)];
|
|
144
|
+
conditions.push([key, accepted]);
|
|
145
|
+
}
|
|
146
|
+
out.push({ conditions, classes });
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
/** Does every condition of a compound rule hold for this selection? */
|
|
151
|
+
function satisfies(rule, selection) {
|
|
152
|
+
for (const [axis, accepted] of rule.conditions) {
|
|
153
|
+
const actual = selection[axis];
|
|
154
|
+
if (actual === undefined)
|
|
155
|
+
return false;
|
|
156
|
+
if (!accepted.includes(actual))
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
function isClassKey(key) {
|
|
162
|
+
return key === "class" || key === "className";
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Narrow a compound rule's `class` / `className` back to `ClassValue`.
|
|
166
|
+
*
|
|
167
|
+
* The value arrives as `unknown` from `entriesOf`; `ClassValue` covers every
|
|
168
|
+
* shape `cn` accepts, so anything that is not a rejected primitive passes
|
|
169
|
+
* through untouched and `cn` does the rest of the work.
|
|
170
|
+
*/
|
|
171
|
+
function isClassValue(value) {
|
|
172
|
+
return (typeof value === "string" ||
|
|
173
|
+
typeof value === "number" ||
|
|
174
|
+
typeof value === "boolean" ||
|
|
175
|
+
value === null ||
|
|
176
|
+
value === undefined ||
|
|
177
|
+
typeof value === "object");
|
|
178
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline icons.
|
|
3
|
+
*
|
|
4
|
+
* shadcn/ui pulls every glyph from `lucide-react`. nebula cannot: it is a
|
|
5
|
+
* React package, and taking a dependency for fifteen paths would undo the
|
|
6
|
+
* point of writing `cn` and `cva` by hand.
|
|
7
|
+
*
|
|
8
|
+
* So the glyphs the component set actually needs are inlined here, traced from
|
|
9
|
+
* Lucide's own 24×24 grid so they sit correctly next to Lucide icons in an app
|
|
10
|
+
* that also uses the real thing. Nothing else is added — this is not an icon
|
|
11
|
+
* library, and an app wanting a hundred more should install one and pass the
|
|
12
|
+
* markup in as content.
|
|
13
|
+
*
|
|
14
|
+
* `currentColor` throughout and no hardcoded size: an icon inherits the text
|
|
15
|
+
* colour of whatever it sits in, and the `[&_svg]:size-4` rules on Button and
|
|
16
|
+
* friends set the size from the component. That is what lets the same icon
|
|
17
|
+
* work in a button, a menu item and a badge without a variant each.
|
|
18
|
+
*/
|
|
19
|
+
import { type TemplateResult } from "@c9up/aurora";
|
|
20
|
+
export interface IconProps {
|
|
21
|
+
class?: string;
|
|
22
|
+
/** Icons are decorative by default; give a label to expose one to a reader. */
|
|
23
|
+
label?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare const CheckIcon: (props?: IconProps) => TemplateResult;
|
|
26
|
+
export declare const MinusIcon: (props?: IconProps) => TemplateResult;
|
|
27
|
+
export declare const XIcon: (props?: IconProps) => TemplateResult;
|
|
28
|
+
export declare const ChevronDownIcon: (props?: IconProps) => TemplateResult;
|
|
29
|
+
export declare const ChevronUpIcon: (props?: IconProps) => TemplateResult;
|
|
30
|
+
export declare const ChevronLeftIcon: (props?: IconProps) => TemplateResult;
|
|
31
|
+
export declare const ChevronRightIcon: (props?: IconProps) => TemplateResult;
|
|
32
|
+
export declare const ChevronsUpDownIcon: (props?: IconProps) => TemplateResult;
|
|
33
|
+
export declare const SearchIcon: (props?: IconProps) => TemplateResult;
|
|
34
|
+
export declare const CircleIcon: (props?: IconProps) => TemplateResult;
|
|
35
|
+
/** Filled dot — the selected marker inside a radio. */
|
|
36
|
+
export declare const DotIcon: (props?: IconProps) => TemplateResult;
|
|
37
|
+
export declare const MoreHorizontalIcon: (props?: IconProps) => TemplateResult;
|
|
38
|
+
export declare const ArrowLeftIcon: (props?: IconProps) => TemplateResult;
|
|
39
|
+
export declare const ArrowRightIcon: (props?: IconProps) => TemplateResult;
|
|
40
|
+
export declare const CalendarIcon: (props?: IconProps) => TemplateResult;
|
|
41
|
+
export declare const PanelLeftIcon: (props?: IconProps) => TemplateResult;
|
|
42
|
+
export declare const GripVerticalIcon: (props?: IconProps) => TemplateResult;
|
|
43
|
+
/** The arc Lucide uses for `loader-circle`; spun by the Spinner's animation. */
|
|
44
|
+
export declare const LoaderIcon: (props?: IconProps) => TemplateResult;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline icons.
|
|
3
|
+
*
|
|
4
|
+
* shadcn/ui pulls every glyph from `lucide-react`. nebula cannot: it is a
|
|
5
|
+
* React package, and taking a dependency for fifteen paths would undo the
|
|
6
|
+
* point of writing `cn` and `cva` by hand.
|
|
7
|
+
*
|
|
8
|
+
* So the glyphs the component set actually needs are inlined here, traced from
|
|
9
|
+
* Lucide's own 24×24 grid so they sit correctly next to Lucide icons in an app
|
|
10
|
+
* that also uses the real thing. Nothing else is added — this is not an icon
|
|
11
|
+
* library, and an app wanting a hundred more should install one and pass the
|
|
12
|
+
* markup in as content.
|
|
13
|
+
*
|
|
14
|
+
* `currentColor` throughout and no hardcoded size: an icon inherits the text
|
|
15
|
+
* colour of whatever it sits in, and the `[&_svg]:size-4` rules on Button and
|
|
16
|
+
* friends set the size from the component. That is what lets the same icon
|
|
17
|
+
* work in a button, a menu item and a badge without a variant each.
|
|
18
|
+
*/
|
|
19
|
+
import { html } from "@c9up/aurora";
|
|
20
|
+
/**
|
|
21
|
+
* Wrap path data in a Lucide-shaped `<svg>`.
|
|
22
|
+
*
|
|
23
|
+
* `aria-hidden` unless labelled, because an icon beside its own text label is
|
|
24
|
+
* noise to a screen reader — it reads the glyph's name and then the text. The
|
|
25
|
+
* exceptions are icon-only controls, which pass a label.
|
|
26
|
+
*/
|
|
27
|
+
function svg(body, props = {}) {
|
|
28
|
+
return html `<svg
|
|
29
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
30
|
+
viewBox="0 0 24 24"
|
|
31
|
+
fill="none"
|
|
32
|
+
stroke="currentColor"
|
|
33
|
+
stroke-width="2"
|
|
34
|
+
stroke-linecap="round"
|
|
35
|
+
stroke-linejoin="round"
|
|
36
|
+
class="${props.class}"
|
|
37
|
+
aria-hidden="${props.label === undefined ? "true" : undefined}"
|
|
38
|
+
aria-label="${props.label}"
|
|
39
|
+
role="${props.label === undefined ? undefined : "img"}"
|
|
40
|
+
>${body}</svg>`;
|
|
41
|
+
}
|
|
42
|
+
export const CheckIcon = (props) => svg(html `<path d="M20 6 9 17l-5-5" />`, props);
|
|
43
|
+
export const MinusIcon = (props) => svg(html `<path d="M5 12h14" />`, props);
|
|
44
|
+
export const XIcon = (props) => svg(html `<path d="M18 6 6 18" /><path d="m6 6 12 12" />`, props);
|
|
45
|
+
export const ChevronDownIcon = (props) => svg(html `<path d="m6 9 6 6 6-6" />`, props);
|
|
46
|
+
export const ChevronUpIcon = (props) => svg(html `<path d="m18 15-6-6-6 6" />`, props);
|
|
47
|
+
export const ChevronLeftIcon = (props) => svg(html `<path d="m15 18-6-6 6-6" />`, props);
|
|
48
|
+
export const ChevronRightIcon = (props) => svg(html `<path d="m9 18 6-6-6-6" />`, props);
|
|
49
|
+
export const ChevronsUpDownIcon = (props) => svg(html `<path d="m7 15 5 5 5-5" /><path d="m7 9 5-5 5 5" />`, props);
|
|
50
|
+
export const SearchIcon = (props) => svg(html `<circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" />`, props);
|
|
51
|
+
export const CircleIcon = (props) => svg(html `<circle cx="12" cy="12" r="10" />`, props);
|
|
52
|
+
/** Filled dot — the selected marker inside a radio. */
|
|
53
|
+
export const DotIcon = (props) => svg(html `<circle cx="12" cy="12" r="4" fill="currentColor" stroke="none" />`, props);
|
|
54
|
+
export const MoreHorizontalIcon = (props) => svg(html `<circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle
|
|
55
|
+
cx="5"
|
|
56
|
+
cy="12"
|
|
57
|
+
r="1"
|
|
58
|
+
/>`, props);
|
|
59
|
+
export const ArrowLeftIcon = (props) => svg(html `<path d="m12 19-7-7 7-7" /><path d="M19 12H5" />`, props);
|
|
60
|
+
export const ArrowRightIcon = (props) => svg(html `<path d="M5 12h14" /><path d="m12 5 7 7-7 7" />`, props);
|
|
61
|
+
export const CalendarIcon = (props) => svg(html `<path d="M8 2v4" /><path d="M16 2v4" /><rect
|
|
62
|
+
width="18"
|
|
63
|
+
height="18"
|
|
64
|
+
x="3"
|
|
65
|
+
y="4"
|
|
66
|
+
rx="2"
|
|
67
|
+
/><path d="M3 10h18" />`, props);
|
|
68
|
+
export const PanelLeftIcon = (props) => svg(html `<rect width="18" height="18" x="3" y="3" rx="2" /><path d="M9 3v18" />`, props);
|
|
69
|
+
export const GripVerticalIcon = (props) => svg(html `<circle cx="9" cy="12" r="1" /><circle cx="9" cy="5" r="1" /><circle
|
|
70
|
+
cx="9"
|
|
71
|
+
cy="19"
|
|
72
|
+
r="1"
|
|
73
|
+
/><circle cx="15" cy="12" r="1" /><circle cx="15" cy="5" r="1" /><circle
|
|
74
|
+
cx="15"
|
|
75
|
+
cy="19"
|
|
76
|
+
r="1"
|
|
77
|
+
/>`, props);
|
|
78
|
+
/** The arc Lucide uses for `loader-circle`; spun by the Spinner's animation. */
|
|
79
|
+
export const LoaderIcon = (props) => svg(html `<path d="M21 12a9 9 0 1 1-6.219-8.56" />`, props);
|