iryx-ui 0.0.1
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 +191 -0
- package/dist/_virtual/_rolldown/runtime.js +11 -0
- package/dist/component-names.d.ts +7 -0
- package/dist/component-names.js +4 -0
- package/dist/components/Button.js +5 -0
- package/dist/components/Button.vue.d.ts +33 -0
- package/dist/components/Button.vue_vue_type_script_setup_true_lang.js +51 -0
- package/dist/components/Switch.js +5 -0
- package/dist/components/Switch.vue.d.ts +18 -0
- package/dist/components/Switch.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +10 -0
- package/dist/composables/appearance.d.ts +23 -0
- package/dist/composables/appearance.js +39 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.js +8 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +10 -0
- package/dist/nuxt.d.ts +14 -0
- package/dist/nuxt.js +38 -0
- package/dist/plugin.d.ts +23 -0
- package/dist/plugin.js +20 -0
- package/dist/theme/button.d.ts +53 -0
- package/dist/theme/button.js +27 -0
- package/dist/theme/index.d.ts +3 -0
- package/dist/theme/presets.d.ts +106 -0
- package/dist/theme/presets.js +98 -0
- package/dist/theme/switch.d.ts +32 -0
- package/dist/theme/switch.js +8 -0
- package/package.json +70 -0
- package/theme.css +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rok Oblak
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# iryx-ui
|
|
2
|
+
|
|
3
|
+
> An artful Vue 3 component library built on [Reka UI](https://reka-ui.com) and [Tailwind CSS v4](https://tailwindcss.com).
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/iryx-ui)
|
|
6
|
+
[](https://github.com/therok1/iryx-ui/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
- ðĻ **Styled by default** â sensible Tailwind v4 themes via [tailwind-variants](https://www.tailwind-variants.org)
|
|
9
|
+
- ð **Light & dark out of the box** â `useAppearance()` with `light` / `dark` / `system`, persisted
|
|
10
|
+
- ð **Swappable themes** â built-in color presets or your own, switchable at runtime with `applyTheme()`
|
|
11
|
+
- ðŠķ **Headless when you want** â `unstyled` per component or globally, leaving bare Reka UI primitives
|
|
12
|
+
- ð§Đ **Composable theming** â override any slot with the `ui` prop or re-brand with CSS theme tokens
|
|
13
|
+
- ⥠**Vue 3 + Nuxt** â a Vue plugin and a Nuxt module with auto-imports, from one package
|
|
14
|
+
- ðģ **Tree-shakeable, ESM-only, fully typed**
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add iryx-ui
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Vue 3 (Vite)
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { IryxUi } from 'iryx-ui'
|
|
26
|
+
// main.ts
|
|
27
|
+
import { createApp } from 'vue'
|
|
28
|
+
import App from './App.vue'
|
|
29
|
+
|
|
30
|
+
createApp(App).use(IryxUi).mount('#app')
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```css
|
|
34
|
+
/* main.css */
|
|
35
|
+
@import "tailwindcss";
|
|
36
|
+
@import "iryx-ui/theme.css";
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Nuxt
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
// nuxt.config.ts
|
|
43
|
+
export default defineNuxtConfig({
|
|
44
|
+
modules: ['iryx-ui/nuxt'],
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
/* assets/css/main.css */
|
|
50
|
+
@import "tailwindcss";
|
|
51
|
+
@import "iryx-ui/theme.css";
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Components are auto-imported with the `I` prefix (configurable via the `iryxUi.prefix` option).
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
```vue
|
|
59
|
+
<template>
|
|
60
|
+
<IButton variant="outline" size="lg">
|
|
61
|
+
Click me
|
|
62
|
+
</IButton>
|
|
63
|
+
<ISwitch v-model="enabled" />
|
|
64
|
+
</template>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Icons
|
|
68
|
+
|
|
69
|
+
Just drop an icon component into the button alongside your text â leading, trailing, or both. Icons are sized automatically to match the button, and spaced for you. Works with any SVG icon set; [lucide-vue-next](https://lucide.dev/guide/packages/lucide-vue-next) pairs nicely:
|
|
70
|
+
|
|
71
|
+
```vue
|
|
72
|
+
<script setup lang="ts">
|
|
73
|
+
import { ArrowRight, Search } from 'lucide-vue-next'
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<template>
|
|
77
|
+
<IButton>
|
|
78
|
+
<Search /> Search
|
|
79
|
+
</IButton>
|
|
80
|
+
<IButton variant="outline">
|
|
81
|
+
Next <ArrowRight />
|
|
82
|
+
</IButton>
|
|
83
|
+
</template>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
When `loading` is set, a spinner appears in the leading position.
|
|
87
|
+
|
|
88
|
+
## Appearance (light / dark)
|
|
89
|
+
|
|
90
|
+
Dark mode is class-based: the `.dark` class on `<html>` flips every token.
|
|
91
|
+
The `useAppearance()` composable manages it for you â it persists the choice
|
|
92
|
+
and follows the OS preference in `system` mode:
|
|
93
|
+
|
|
94
|
+
```vue
|
|
95
|
+
<script setup>
|
|
96
|
+
import { useAppearance } from 'iryx-ui'
|
|
97
|
+
|
|
98
|
+
const { appearance, isDark, setAppearance, toggleAppearance } = useAppearance()
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<template>
|
|
102
|
+
<IButton variant="ghost" @click="toggleAppearance()">
|
|
103
|
+
{{ isDark ? 'ð' : 'âïļ' }}
|
|
104
|
+
</IButton>
|
|
105
|
+
</template>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
You can set the startup default via the plugin or Nuxt module (a stored user
|
|
109
|
+
preference always wins):
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
app.use(createIryxUi({ appearance: 'system' }))
|
|
113
|
+
// nuxt.config.ts â iryxUi: { appearance: 'system' }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`theme.css` also registers the class-based `dark:` variant for your own
|
|
117
|
+
utilities (shadcn-style `@custom-variant dark`).
|
|
118
|
+
|
|
119
|
+
## Theming
|
|
120
|
+
|
|
121
|
+
Pick a built-in color preset â `violet` (default), `emerald`, `rose`,
|
|
122
|
+
`amber`, `sky` â at startup or at runtime:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { applyTheme } from 'iryx-ui'
|
|
126
|
+
|
|
127
|
+
app.use(createIryxUi({ theme: 'emerald' }))
|
|
128
|
+
// nuxt.config.ts â iryxUi: { theme: 'emerald' }
|
|
129
|
+
|
|
130
|
+
applyTheme('rose') // runtime, e.g. from a theme picker
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Or bring your own theme â every token can differ between light and dark:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
applyTheme({
|
|
137
|
+
light: { primary: 'oklch(0.55 0.2 250)', primaryForeground: 'white' },
|
|
138
|
+
dark: { primary: 'oklch(0.68 0.17 250)', primaryForeground: 'oklch(0.15 0.04 250)' },
|
|
139
|
+
})
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
For a static re-brand, plain CSS works too â tokens are just variables:
|
|
143
|
+
|
|
144
|
+
```css
|
|
145
|
+
:root {
|
|
146
|
+
--iryx-primary: oklch(0.65 0.2 145); /* make it green */
|
|
147
|
+
}
|
|
148
|
+
.dark {
|
|
149
|
+
--iryx-primary: oklch(0.75 0.18 145);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Available tokens: `background`, `foreground`, `primary`, `primary-foreground`,
|
|
154
|
+
`accent`, `accent-foreground`, `muted`, `muted-foreground`, `border` â each
|
|
155
|
+
usable as a Tailwind color (`bg-primary`, `text-muted-foreground`, âĶ).
|
|
156
|
+
|
|
157
|
+
Tweak a single instance with `class` (conflicts are merged smartly) or per-slot with `ui`:
|
|
158
|
+
|
|
159
|
+
```vue
|
|
160
|
+
<IButton class="rounded-full">
|
|
161
|
+
Pill button
|
|
162
|
+
</IButton>
|
|
163
|
+
|
|
164
|
+
<ISwitch :ui="{ thumb: 'bg-zinc-900' }" />
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Or drop all built-in styles and take over completely:
|
|
168
|
+
|
|
169
|
+
```vue
|
|
170
|
+
<IButton unstyled class="my-own-button">
|
|
171
|
+
Headless
|
|
172
|
+
</IButton>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// âĶor globally:
|
|
177
|
+
app.use(createIryxUi({ unstyled: true }))
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Components
|
|
181
|
+
|
|
182
|
+
| Component | Description |
|
|
183
|
+
| --- | --- |
|
|
184
|
+
| `IButton` | Variants (`solid`, `outline`, `ghost`, `link`), five sizes, `loading` and `block` states, polymorphic via `as` / `asChild` |
|
|
185
|
+
| `ISwitch` | Accessible toggle built on Reka UI's Switch |
|
|
186
|
+
|
|
187
|
+
More on the way.
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
[MIT](https://github.com/therok1/iryx-ui/blob/main/LICENSE)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var e = Object.defineProperty, t = (t, n) => {
|
|
3
|
+
let r = {};
|
|
4
|
+
for (var i in t) e(r, i, {
|
|
5
|
+
get: t[i],
|
|
6
|
+
enumerable: !0
|
|
7
|
+
});
|
|
8
|
+
return n || e(r, Symbol.toStringTag, { value: "Module" }), r;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { t as __exportAll };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Names of every component exported from the package root.
|
|
3
|
+
* Consumed by the Vue plugin (global registration) and the Nuxt module
|
|
4
|
+
* (auto-imports). Keep in sync with `src/components/index.ts`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const componentNames: readonly ["Button", "Switch"];
|
|
7
|
+
export type ComponentName = (typeof componentNames)[number];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface ButtonProps {
|
|
2
|
+
/** Render as a different element or component. */
|
|
3
|
+
as?: string;
|
|
4
|
+
/** Merge props onto the immediate child instead of rendering an element. */
|
|
5
|
+
asChild?: boolean;
|
|
6
|
+
variant?: 'solid' | 'outline' | 'ghost' | 'link';
|
|
7
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
8
|
+
/** Stretch to the full width of the container. */
|
|
9
|
+
block?: boolean;
|
|
10
|
+
/** Show a spinner (in the leading position) and disable interaction. */
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
/** Skip built-in classes; you take over styling entirely. */
|
|
14
|
+
unstyled?: boolean;
|
|
15
|
+
type?: 'button' | 'submit' | 'reset';
|
|
16
|
+
class?: string;
|
|
17
|
+
}
|
|
18
|
+
declare var __VLS_13: {};
|
|
19
|
+
type __VLS_Slots = {} & {
|
|
20
|
+
default?: (props: typeof __VLS_13) => any;
|
|
21
|
+
};
|
|
22
|
+
declare const __VLS_base: import("vue").DefineComponent<ButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ButtonProps> & Readonly<{}>, {
|
|
23
|
+
as: string;
|
|
24
|
+
type: "button" | "submit" | "reset";
|
|
25
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
26
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
27
|
+
declare const _default: typeof __VLS_export;
|
|
28
|
+
export default _default;
|
|
29
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
30
|
+
new (): {
|
|
31
|
+
$slots: S;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useIryxUiConfig as e } from "../config.js";
|
|
2
|
+
import { buttonTheme as t } from "../theme/button.js";
|
|
3
|
+
import { computed as n, createBlock as r, createCommentVNode as i, defineComponent as a, normalizeClass as o, openBlock as s, renderSlot as c, unref as l, withCtx as u } from "vue";
|
|
4
|
+
import { LoaderCircle as d } from "lucide-vue-next";
|
|
5
|
+
import { Primitive as f } from "reka-ui";
|
|
6
|
+
//#region src/components/Button.vue?vue&type=script&setup=true&lang.ts
|
|
7
|
+
var p = /*@__PURE__*/ a({
|
|
8
|
+
__name: "Button",
|
|
9
|
+
props: {
|
|
10
|
+
as: { default: "button" },
|
|
11
|
+
asChild: { type: Boolean },
|
|
12
|
+
variant: {},
|
|
13
|
+
size: {},
|
|
14
|
+
block: { type: Boolean },
|
|
15
|
+
loading: { type: Boolean },
|
|
16
|
+
disabled: { type: Boolean },
|
|
17
|
+
unstyled: { type: Boolean },
|
|
18
|
+
type: { default: "button" },
|
|
19
|
+
class: {}
|
|
20
|
+
},
|
|
21
|
+
setup(a) {
|
|
22
|
+
let p = a, m = e(), h = n(() => p.unstyled ?? m.unstyled), g = n(() => h.value ? p.class : t({
|
|
23
|
+
variant: p.variant,
|
|
24
|
+
size: p.size,
|
|
25
|
+
block: p.block,
|
|
26
|
+
class: p.class
|
|
27
|
+
}));
|
|
28
|
+
return (e, t) => (s(), r(l(f), {
|
|
29
|
+
as: p.as,
|
|
30
|
+
"as-child": p.asChild,
|
|
31
|
+
type: p.as === "button" ? p.type : void 0,
|
|
32
|
+
disabled: p.disabled || p.loading || void 0,
|
|
33
|
+
class: o(g.value)
|
|
34
|
+
}, {
|
|
35
|
+
default: u(() => [p.loading ? (s(), r(l(d), {
|
|
36
|
+
key: 0,
|
|
37
|
+
class: "animate-spin",
|
|
38
|
+
"aria-hidden": "true"
|
|
39
|
+
})) : i("", !0), c(e.$slots, "default")]),
|
|
40
|
+
_: 3
|
|
41
|
+
}, 8, [
|
|
42
|
+
"as",
|
|
43
|
+
"as-child",
|
|
44
|
+
"type",
|
|
45
|
+
"disabled",
|
|
46
|
+
"class"
|
|
47
|
+
]));
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
//#endregion
|
|
51
|
+
export { p as default };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SwitchRootProps } from 'reka-ui';
|
|
2
|
+
export interface SwitchProps extends SwitchRootProps {
|
|
3
|
+
/** Skip built-in classes; you take over styling entirely. */
|
|
4
|
+
unstyled?: boolean;
|
|
5
|
+
class?: string;
|
|
6
|
+
/** Override classes per slot, e.g. `{ thumb: 'bg-black' }`. */
|
|
7
|
+
ui?: {
|
|
8
|
+
root?: string;
|
|
9
|
+
thumb?: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<SwitchProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
|
+
"update:modelValue": (payload: boolean) => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<SwitchProps> & Readonly<{
|
|
15
|
+
"onUpdate:modelValue"?: ((payload: boolean) => any) | undefined;
|
|
16
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useIryxUiConfig as e } from "../config.js";
|
|
2
|
+
import { switchTheme as t } from "../theme/switch.js";
|
|
3
|
+
import { computed as n, createBlock as r, createVNode as i, defineComponent as a, mergeProps as o, normalizeClass as s, openBlock as c, unref as l, withCtx as u } from "vue";
|
|
4
|
+
import { SwitchRoot as d, SwitchThumb as f, useForwardPropsEmits as p } from "reka-ui";
|
|
5
|
+
//#region src/components/Switch.vue?vue&type=script&setup=true&lang.ts
|
|
6
|
+
var m = /*@__PURE__*/ a({
|
|
7
|
+
__name: "Switch",
|
|
8
|
+
props: {
|
|
9
|
+
unstyled: { type: Boolean },
|
|
10
|
+
class: {},
|
|
11
|
+
ui: {},
|
|
12
|
+
defaultValue: {},
|
|
13
|
+
modelValue: {},
|
|
14
|
+
disabled: { type: Boolean },
|
|
15
|
+
id: {},
|
|
16
|
+
value: {},
|
|
17
|
+
trueValue: {},
|
|
18
|
+
falseValue: {},
|
|
19
|
+
asChild: { type: Boolean },
|
|
20
|
+
as: {},
|
|
21
|
+
name: {},
|
|
22
|
+
required: { type: Boolean }
|
|
23
|
+
},
|
|
24
|
+
emits: ["update:modelValue"],
|
|
25
|
+
setup(a, { emit: m }) {
|
|
26
|
+
let h = a, g = m, _ = p(n(() => {
|
|
27
|
+
let { unstyled: e, class: t, ui: n, ...r } = h;
|
|
28
|
+
return r;
|
|
29
|
+
}), g), v = e(), y = n(() => h.unstyled ?? v.unstyled), b = t(), x = n(() => y.value ? [h.ui?.root, h.class] : b.root({ class: [h.ui?.root, h.class] })), S = n(() => y.value ? h.ui?.thumb : b.thumb({ class: h.ui?.thumb }));
|
|
30
|
+
return (e, t) => (c(), r(l(d), o(l(_), { class: x.value }), {
|
|
31
|
+
default: u(() => [i(l(f), { class: s(S.value) }, null, 8, ["class"])]),
|
|
32
|
+
_: 1
|
|
33
|
+
}, 16, ["class"]));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
//#endregion
|
|
37
|
+
export { m as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { __exportAll as e } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import t from "./Button.js";
|
|
3
|
+
import n from "./Switch.js";
|
|
4
|
+
//#region src/components/index.ts
|
|
5
|
+
var r = /* @__PURE__ */ e({
|
|
6
|
+
Button: () => t,
|
|
7
|
+
Switch: () => n
|
|
8
|
+
});
|
|
9
|
+
//#endregion
|
|
10
|
+
export { r as components_exports };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ComputedRef, Ref } from 'vue';
|
|
2
|
+
export type Appearance = 'light' | 'dark' | 'system';
|
|
3
|
+
/**
|
|
4
|
+
* Set the startup appearance, unless the user already has a stored
|
|
5
|
+
* preference (their choice wins). Used by the plugin/module options;
|
|
6
|
+
* no-op during SSR.
|
|
7
|
+
*/
|
|
8
|
+
export declare function initAppearance(defaultAppearance: Appearance): void;
|
|
9
|
+
export interface UseAppearanceReturn {
|
|
10
|
+
/** The selected mode: `light`, `dark`, or `system`. Shared app-wide. */
|
|
11
|
+
appearance: Ref<Appearance>;
|
|
12
|
+
/** Whether dark mode is effectively active (resolves `system`). */
|
|
13
|
+
isDark: ComputedRef<boolean>;
|
|
14
|
+
setAppearance: (value: Appearance) => void;
|
|
15
|
+
/** Flip between light and dark based on the currently effective mode. */
|
|
16
|
+
toggleAppearance: () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Light/dark mode for the app. Persists to localStorage, follows the OS
|
|
20
|
+
* preference in `system` mode, and toggles the `dark` class on `<html>`
|
|
21
|
+
* (which drives the `.dark` token block in theme.css).
|
|
22
|
+
*/
|
|
23
|
+
export declare function useAppearance(): UseAppearanceReturn;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { computed as e, ref as t, watchEffect as n } from "vue";
|
|
2
|
+
//#region src/composables/appearance.ts
|
|
3
|
+
var r = "iryx-ui:appearance", i = t("system"), a = t(!1), o = !1;
|
|
4
|
+
function s() {
|
|
5
|
+
return i.value === "dark" || i.value === "system" && a.value;
|
|
6
|
+
}
|
|
7
|
+
function c() {
|
|
8
|
+
if (o || typeof window > "u") return;
|
|
9
|
+
o = !0;
|
|
10
|
+
let e = window.localStorage.getItem(r);
|
|
11
|
+
if ((e === "light" || e === "dark" || e === "system") && (i.value = e), typeof window.matchMedia == "function") {
|
|
12
|
+
let e = window.matchMedia("(prefers-color-scheme: dark)");
|
|
13
|
+
a.value = e.matches, e.addEventListener("change", (e) => {
|
|
14
|
+
a.value = e.matches;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
n(() => {
|
|
18
|
+
document.documentElement.classList.toggle("dark", s()), window.localStorage.setItem(r, i.value);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function l(e) {
|
|
22
|
+
if (typeof window > "u") return;
|
|
23
|
+
let t = window.localStorage.getItem(r) !== null;
|
|
24
|
+
c(), t || (i.value = e);
|
|
25
|
+
}
|
|
26
|
+
function u() {
|
|
27
|
+
return c(), {
|
|
28
|
+
appearance: i,
|
|
29
|
+
isDark: e(() => s()),
|
|
30
|
+
setAppearance: (e) => {
|
|
31
|
+
i.value = e;
|
|
32
|
+
},
|
|
33
|
+
toggleAppearance: () => {
|
|
34
|
+
i.value = s() ? "light" : "dark";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { l as initAppearance, u as useAppearance };
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { InjectionKey } from 'vue';
|
|
2
|
+
export interface IryxUiConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Skip all built-in Tailwind classes and render bare Reka UI primitives.
|
|
5
|
+
* Can also be toggled per component via the `unstyled` prop.
|
|
6
|
+
*/
|
|
7
|
+
unstyled: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const defaultConfig: IryxUiConfig;
|
|
10
|
+
export declare const iryxUiConfigKey: InjectionKey<IryxUiConfig>;
|
|
11
|
+
export declare function useIryxUiConfig(): IryxUiConfig;
|
package/dist/config.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { componentNames } from './component-names';
|
|
2
|
+
export type { ComponentName } from './component-names';
|
|
3
|
+
export * from './components';
|
|
4
|
+
export type { ButtonProps } from './components/Button.vue';
|
|
5
|
+
export type { SwitchProps } from './components/Switch.vue';
|
|
6
|
+
export * from './composables/appearance';
|
|
7
|
+
export { defaultConfig, iryxUiConfigKey, useIryxUiConfig } from './config';
|
|
8
|
+
export type { IryxUiConfig } from './config';
|
|
9
|
+
export { createIryxUi, IryxUi } from './plugin';
|
|
10
|
+
export type { IryxUiPluginOptions } from './plugin';
|
|
11
|
+
export * from './theme';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { componentNames as e } from "./component-names.js";
|
|
2
|
+
import { defaultConfig as t, iryxUiConfigKey as n, useIryxUiConfig as r } from "./config.js";
|
|
3
|
+
import { buttonTheme as i } from "./theme/button.js";
|
|
4
|
+
import a from "./components/Button.js";
|
|
5
|
+
import { switchTheme as o } from "./theme/switch.js";
|
|
6
|
+
import s from "./components/Switch.js";
|
|
7
|
+
import { initAppearance as c, useAppearance as l } from "./composables/appearance.js";
|
|
8
|
+
import { applyTheme as u, clearTheme as d, themes as f } from "./theme/presets.js";
|
|
9
|
+
import { IryxUi as p, createIryxUi as m } from "./plugin.js";
|
|
10
|
+
export { a as Button, p as IryxUi, s as Switch, u as applyTheme, i as buttonTheme, d as clearTheme, e as componentNames, m as createIryxUi, t as defaultConfig, c as initAppearance, n as iryxUiConfigKey, o as switchTheme, f as themes, l as useAppearance, r as useIryxUiConfig };
|
package/dist/nuxt.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Appearance } from './composables/appearance';
|
|
2
|
+
import type { Theme, ThemePresetName } from './theme/presets';
|
|
3
|
+
export interface ModuleOptions {
|
|
4
|
+
/** Prefix for auto-imported components. Defaults to `I` (IButton, ISwitchâĶ). */
|
|
5
|
+
prefix: string;
|
|
6
|
+
/** Render bare Reka UI primitives without Iryx's Tailwind classes. */
|
|
7
|
+
unstyled: boolean;
|
|
8
|
+
/** Startup appearance. A preference the user already stored wins over this. */
|
|
9
|
+
appearance?: Appearance;
|
|
10
|
+
/** Color theme: a preset name (`'emerald'`, `'rose'`âĶ) or a custom theme. */
|
|
11
|
+
theme?: Theme | ThemePresetName;
|
|
12
|
+
}
|
|
13
|
+
declare const _default: NuxtModule<TOptions, TOptions, false>;
|
|
14
|
+
export default _default;
|
package/dist/nuxt.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { componentNames as e } from "./component-names.js";
|
|
2
|
+
import { addComponent as t, addPluginTemplate as n, defineNuxtModule as r } from "@nuxt/kit";
|
|
3
|
+
//#region src/nuxt.ts
|
|
4
|
+
var i = r({
|
|
5
|
+
meta: {
|
|
6
|
+
name: "iryx-ui",
|
|
7
|
+
configKey: "iryxUi",
|
|
8
|
+
compatibility: { nuxt: ">=3.0.0" }
|
|
9
|
+
},
|
|
10
|
+
defaults: {
|
|
11
|
+
prefix: "I",
|
|
12
|
+
unstyled: !1
|
|
13
|
+
},
|
|
14
|
+
setup(r) {
|
|
15
|
+
for (let n of e) t({
|
|
16
|
+
name: `${r.prefix}${n}`,
|
|
17
|
+
export: n,
|
|
18
|
+
filePath: "iryx-ui"
|
|
19
|
+
});
|
|
20
|
+
n({
|
|
21
|
+
filename: "iryx-ui.config.mjs",
|
|
22
|
+
getContents: () => `
|
|
23
|
+
import { applyTheme, initAppearance, iryxUiConfigKey } from 'iryx-ui'
|
|
24
|
+
import { defineNuxtPlugin } from '#app'
|
|
25
|
+
|
|
26
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
27
|
+
nuxtApp.vueApp.provide(iryxUiConfigKey, ${JSON.stringify({ unstyled: r.unstyled })})
|
|
28
|
+
if (import.meta.client) {
|
|
29
|
+
${r.theme ? `applyTheme(${JSON.stringify(r.theme)})` : ""}
|
|
30
|
+
${r.appearance ? `initAppearance(${JSON.stringify(r.appearance)})` : ""}
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
`
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
//#endregion
|
|
38
|
+
export { i as default };
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Plugin } from 'vue';
|
|
2
|
+
import type { Appearance } from './composables/appearance';
|
|
3
|
+
import type { IryxUiConfig } from './config';
|
|
4
|
+
import type { Theme, ThemePresetName } from './theme/presets';
|
|
5
|
+
export interface IryxUiPluginOptions extends Partial<IryxUiConfig> {
|
|
6
|
+
/** Prefix for globally registered components. Defaults to `I` (IButton, ISwitchâĶ). */
|
|
7
|
+
prefix?: string;
|
|
8
|
+
/** Startup appearance. A preference the user already stored wins over this. */
|
|
9
|
+
appearance?: Appearance;
|
|
10
|
+
/** Color theme: a preset name (`'emerald'`, `'rose'`âĶ) or a custom theme. */
|
|
11
|
+
theme?: Theme | ThemePresetName;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create the Iryx UI Vue plugin. Registers every component globally
|
|
15
|
+
* (prefixed) and provides the global config.
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* app.use(createIryxUi({ prefix: 'I', unstyled: false }))
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function createIryxUi(options?: IryxUiPluginOptions): Plugin;
|
|
22
|
+
/** The Iryx UI Vue plugin with default options. */
|
|
23
|
+
export declare const IryxUi: Plugin;
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { componentNames as e } from "./component-names.js";
|
|
2
|
+
import { defaultConfig as t, iryxUiConfigKey as n } from "./config.js";
|
|
3
|
+
import { components_exports as r } from "./components/index.js";
|
|
4
|
+
import { initAppearance as i } from "./composables/appearance.js";
|
|
5
|
+
import { applyTheme as a } from "./theme/presets.js";
|
|
6
|
+
//#region src/plugin.ts
|
|
7
|
+
function o(o = {}) {
|
|
8
|
+
let { prefix: s = "I", appearance: c, theme: l, ...u } = o;
|
|
9
|
+
return { install(o) {
|
|
10
|
+
o.provide(n, {
|
|
11
|
+
...t,
|
|
12
|
+
...u
|
|
13
|
+
});
|
|
14
|
+
for (let t of e) o.component(`${s}${t}`, r[t]);
|
|
15
|
+
l && a(l), c && i(c);
|
|
16
|
+
} };
|
|
17
|
+
}
|
|
18
|
+
var s = o();
|
|
19
|
+
//#endregion
|
|
20
|
+
export { s as IryxUi, o as createIryxUi };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export declare const buttonTheme: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
variant: {
|
|
3
|
+
solid: string;
|
|
4
|
+
outline: string;
|
|
5
|
+
ghost: string;
|
|
6
|
+
link: string;
|
|
7
|
+
};
|
|
8
|
+
size: {
|
|
9
|
+
xs: string;
|
|
10
|
+
sm: string;
|
|
11
|
+
md: string;
|
|
12
|
+
lg: string;
|
|
13
|
+
xl: string;
|
|
14
|
+
};
|
|
15
|
+
block: {
|
|
16
|
+
true: string;
|
|
17
|
+
};
|
|
18
|
+
}, undefined, "inline-flex shrink-0 items-center justify-center gap-2 rounded-lg font-medium transition-all outline-none focus-visible:ring-2 focus-visible:ring-primary/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", {
|
|
19
|
+
variant: {
|
|
20
|
+
solid: string;
|
|
21
|
+
outline: string;
|
|
22
|
+
ghost: string;
|
|
23
|
+
link: string;
|
|
24
|
+
};
|
|
25
|
+
size: {
|
|
26
|
+
xs: string;
|
|
27
|
+
sm: string;
|
|
28
|
+
md: string;
|
|
29
|
+
lg: string;
|
|
30
|
+
xl: string;
|
|
31
|
+
};
|
|
32
|
+
block: {
|
|
33
|
+
true: string;
|
|
34
|
+
};
|
|
35
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
36
|
+
variant: {
|
|
37
|
+
solid: string;
|
|
38
|
+
outline: string;
|
|
39
|
+
ghost: string;
|
|
40
|
+
link: string;
|
|
41
|
+
};
|
|
42
|
+
size: {
|
|
43
|
+
xs: string;
|
|
44
|
+
sm: string;
|
|
45
|
+
md: string;
|
|
46
|
+
lg: string;
|
|
47
|
+
xl: string;
|
|
48
|
+
};
|
|
49
|
+
block: {
|
|
50
|
+
true: string;
|
|
51
|
+
};
|
|
52
|
+
}, undefined, "inline-flex shrink-0 items-center justify-center gap-2 rounded-lg font-medium transition-all outline-none focus-visible:ring-2 focus-visible:ring-primary/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", unknown, unknown, undefined>>;
|
|
53
|
+
export type ButtonVariants = Parameters<typeof buttonTheme>[0];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { tv as e } from "tailwind-variants";
|
|
2
|
+
//#region src/theme/button.ts
|
|
3
|
+
var t = e({
|
|
4
|
+
base: "inline-flex shrink-0 items-center justify-center gap-2 rounded-lg font-medium transition-all outline-none focus-visible:ring-2 focus-visible:ring-primary/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
5
|
+
variants: {
|
|
6
|
+
variant: {
|
|
7
|
+
solid: "bg-linear-to-b from-primary-from to-primary-to text-primary-foreground hover:brightness-110 active:brightness-95",
|
|
8
|
+
outline: "border border-border bg-background text-foreground hover:bg-accent hover:text-accent-foreground",
|
|
9
|
+
ghost: "text-foreground hover:bg-accent hover:text-accent-foreground",
|
|
10
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
11
|
+
},
|
|
12
|
+
size: {
|
|
13
|
+
xs: "h-7 gap-1.5 px-2 text-xs [&_svg]:size-3.5",
|
|
14
|
+
sm: "h-8 px-3 text-sm [&_svg]:size-4",
|
|
15
|
+
md: "h-9 px-4 text-sm [&_svg]:size-4",
|
|
16
|
+
lg: "h-10 px-5 text-base [&_svg]:size-5",
|
|
17
|
+
xl: "h-12 px-6 text-base [&_svg]:size-5"
|
|
18
|
+
},
|
|
19
|
+
block: { true: "w-full" }
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: {
|
|
22
|
+
variant: "solid",
|
|
23
|
+
size: "md"
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
//#endregion
|
|
27
|
+
export { t as buttonTheme };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export interface ThemeColors {
|
|
2
|
+
background?: string;
|
|
3
|
+
foreground?: string;
|
|
4
|
+
primary?: string;
|
|
5
|
+
primaryForeground?: string;
|
|
6
|
+
/** Top stop of the solid button's vertical gradient. */
|
|
7
|
+
primaryFrom?: string;
|
|
8
|
+
/** Bottom stop of the solid button's vertical gradient. */
|
|
9
|
+
primaryTo?: string;
|
|
10
|
+
accent?: string;
|
|
11
|
+
accentForeground?: string;
|
|
12
|
+
muted?: string;
|
|
13
|
+
mutedForeground?: string;
|
|
14
|
+
border?: string;
|
|
15
|
+
}
|
|
16
|
+
/** A theme provides token values per appearance mode. Omitted tokens keep the defaults from theme.css. */
|
|
17
|
+
export interface Theme {
|
|
18
|
+
light: ThemeColors;
|
|
19
|
+
dark: ThemeColors;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Built-in theme presets. Each swaps only the brand primary (solid colour +
|
|
23
|
+
* gradient stops); neutral surfaces stay on the shadcn-style palette from
|
|
24
|
+
* theme.css, so every theme shares the same chrome.
|
|
25
|
+
*/
|
|
26
|
+
export declare const themes: {
|
|
27
|
+
violet: {
|
|
28
|
+
light: {
|
|
29
|
+
primary: string;
|
|
30
|
+
primaryForeground: string;
|
|
31
|
+
primaryFrom: string;
|
|
32
|
+
primaryTo: string;
|
|
33
|
+
};
|
|
34
|
+
dark: {
|
|
35
|
+
primary: string;
|
|
36
|
+
primaryForeground: string;
|
|
37
|
+
primaryFrom: string;
|
|
38
|
+
primaryTo: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
emerald: {
|
|
42
|
+
light: {
|
|
43
|
+
primary: string;
|
|
44
|
+
primaryForeground: string;
|
|
45
|
+
primaryFrom: string;
|
|
46
|
+
primaryTo: string;
|
|
47
|
+
};
|
|
48
|
+
dark: {
|
|
49
|
+
primary: string;
|
|
50
|
+
primaryForeground: string;
|
|
51
|
+
primaryFrom: string;
|
|
52
|
+
primaryTo: string;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
rose: {
|
|
56
|
+
light: {
|
|
57
|
+
primary: string;
|
|
58
|
+
primaryForeground: string;
|
|
59
|
+
primaryFrom: string;
|
|
60
|
+
primaryTo: string;
|
|
61
|
+
};
|
|
62
|
+
dark: {
|
|
63
|
+
primary: string;
|
|
64
|
+
primaryForeground: string;
|
|
65
|
+
primaryFrom: string;
|
|
66
|
+
primaryTo: string;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
amber: {
|
|
70
|
+
light: {
|
|
71
|
+
primary: string;
|
|
72
|
+
primaryForeground: string;
|
|
73
|
+
primaryFrom: string;
|
|
74
|
+
primaryTo: string;
|
|
75
|
+
};
|
|
76
|
+
dark: {
|
|
77
|
+
primary: string;
|
|
78
|
+
primaryForeground: string;
|
|
79
|
+
primaryFrom: string;
|
|
80
|
+
primaryTo: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
sky: {
|
|
84
|
+
light: {
|
|
85
|
+
primary: string;
|
|
86
|
+
primaryForeground: string;
|
|
87
|
+
primaryFrom: string;
|
|
88
|
+
primaryTo: string;
|
|
89
|
+
};
|
|
90
|
+
dark: {
|
|
91
|
+
primary: string;
|
|
92
|
+
primaryForeground: string;
|
|
93
|
+
primaryFrom: string;
|
|
94
|
+
primaryTo: string;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
export type ThemePresetName = keyof typeof themes;
|
|
99
|
+
/**
|
|
100
|
+
* Apply a theme at runtime by injecting a stylesheet that overrides the
|
|
101
|
+
* Iryx token variables for both light (`:root`) and dark (`.dark`) modes.
|
|
102
|
+
* Pass a preset name or a custom {@link Theme}. No-op during SSR.
|
|
103
|
+
*/
|
|
104
|
+
export declare function applyTheme(theme: Theme | ThemePresetName): void;
|
|
105
|
+
/** Remove a theme applied with {@link applyTheme}, restoring theme.css defaults. */
|
|
106
|
+
export declare function clearTheme(): void;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
//#region src/theme/presets.ts
|
|
2
|
+
var e = {
|
|
3
|
+
background: "--iryx-background",
|
|
4
|
+
foreground: "--iryx-foreground",
|
|
5
|
+
primary: "--iryx-primary",
|
|
6
|
+
primaryForeground: "--iryx-primary-foreground",
|
|
7
|
+
primaryFrom: "--iryx-primary-from",
|
|
8
|
+
primaryTo: "--iryx-primary-to",
|
|
9
|
+
accent: "--iryx-accent",
|
|
10
|
+
accentForeground: "--iryx-accent-foreground",
|
|
11
|
+
muted: "--iryx-muted",
|
|
12
|
+
mutedForeground: "--iryx-muted-foreground",
|
|
13
|
+
border: "--iryx-border"
|
|
14
|
+
}, t = {
|
|
15
|
+
violet: {
|
|
16
|
+
light: {
|
|
17
|
+
primary: "oklch(0.59 0.2 277.19)",
|
|
18
|
+
primaryForeground: "oklch(0.985 0.005 248)",
|
|
19
|
+
primaryFrom: "oklch(0.59 0.2 277.19)",
|
|
20
|
+
primaryTo: "oklch(0.51 0.23 276.99)"
|
|
21
|
+
},
|
|
22
|
+
dark: {
|
|
23
|
+
primary: "oklch(0.62 0.22 293)",
|
|
24
|
+
primaryForeground: "oklch(0.985 0.005 248)",
|
|
25
|
+
primaryFrom: "oklch(0.62 0.22 293)",
|
|
26
|
+
primaryTo: "oklch(0.54 0.24 293)"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
emerald: {
|
|
30
|
+
light: {
|
|
31
|
+
primary: "oklch(0.596 0.145 163)",
|
|
32
|
+
primaryForeground: "oklch(0.985 0.005 248)",
|
|
33
|
+
primaryFrom: "oklch(0.596 0.145 163)",
|
|
34
|
+
primaryTo: "oklch(0.52 0.155 163)"
|
|
35
|
+
},
|
|
36
|
+
dark: {
|
|
37
|
+
primary: "oklch(0.7 0.15 162)",
|
|
38
|
+
primaryForeground: "oklch(0.17 0.04 165)",
|
|
39
|
+
primaryFrom: "oklch(0.7 0.15 162)",
|
|
40
|
+
primaryTo: "oklch(0.62 0.16 162)"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
rose: {
|
|
44
|
+
light: {
|
|
45
|
+
primary: "oklch(0.586 0.222 17)",
|
|
46
|
+
primaryForeground: "oklch(0.985 0.005 248)",
|
|
47
|
+
primaryFrom: "oklch(0.586 0.222 17)",
|
|
48
|
+
primaryTo: "oklch(0.51 0.235 17)"
|
|
49
|
+
},
|
|
50
|
+
dark: {
|
|
51
|
+
primary: "oklch(0.65 0.22 16)",
|
|
52
|
+
primaryForeground: "oklch(0.985 0.005 248)",
|
|
53
|
+
primaryFrom: "oklch(0.65 0.22 16)",
|
|
54
|
+
primaryTo: "oklch(0.57 0.235 16)"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
amber: {
|
|
58
|
+
light: {
|
|
59
|
+
primary: "oklch(0.666 0.157 58)",
|
|
60
|
+
primaryForeground: "oklch(0.16 0.03 80)",
|
|
61
|
+
primaryFrom: "oklch(0.666 0.157 58)",
|
|
62
|
+
primaryTo: "oklch(0.59 0.165 56)"
|
|
63
|
+
},
|
|
64
|
+
dark: {
|
|
65
|
+
primary: "oklch(0.77 0.16 70)",
|
|
66
|
+
primaryForeground: "oklch(0.18 0.04 75)",
|
|
67
|
+
primaryFrom: "oklch(0.77 0.16 70)",
|
|
68
|
+
primaryTo: "oklch(0.7 0.17 68)"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
sky: {
|
|
72
|
+
light: {
|
|
73
|
+
primary: "oklch(0.588 0.13 242)",
|
|
74
|
+
primaryForeground: "oklch(0.985 0.005 248)",
|
|
75
|
+
primaryFrom: "oklch(0.588 0.13 242)",
|
|
76
|
+
primaryTo: "oklch(0.51 0.14 242)"
|
|
77
|
+
},
|
|
78
|
+
dark: {
|
|
79
|
+
primary: "oklch(0.685 0.14 237)",
|
|
80
|
+
primaryForeground: "oklch(0.15 0.04 240)",
|
|
81
|
+
primaryFrom: "oklch(0.685 0.14 237)",
|
|
82
|
+
primaryTo: "oklch(0.6 0.15 237)"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}, n = "iryx-ui-theme";
|
|
86
|
+
function r(t) {
|
|
87
|
+
return Object.keys(t).filter((e) => t[e] != null).map((n) => `${e[n]}: ${t[n]};`).join(" ");
|
|
88
|
+
}
|
|
89
|
+
function i(e) {
|
|
90
|
+
if (typeof document > "u") return;
|
|
91
|
+
let i = typeof e == "string" ? t[e] : e, a = document.getElementById(n);
|
|
92
|
+
a || (a = document.createElement("style"), a.id = n, document.head.appendChild(a)), a.textContent = `:root { ${r(i.light)} }\n.dark { ${r(i.dark)} }`;
|
|
93
|
+
}
|
|
94
|
+
function a() {
|
|
95
|
+
typeof document > "u" || document.getElementById(n)?.remove();
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
export { i as applyTheme, a as clearTheme, t as themes };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const switchTheme: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
[key: string]: {
|
|
3
|
+
[key: string]: import("tailwind-variants").ClassValue | {
|
|
4
|
+
root?: import("tailwind-variants").ClassValue;
|
|
5
|
+
thumb?: import("tailwind-variants").ClassValue;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
} | {
|
|
9
|
+
[x: string]: {
|
|
10
|
+
[x: string]: import("tailwind-variants").ClassValue | {
|
|
11
|
+
root?: import("tailwind-variants").ClassValue;
|
|
12
|
+
thumb?: import("tailwind-variants").ClassValue;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
} | {}, {
|
|
16
|
+
root: string;
|
|
17
|
+
thumb: string;
|
|
18
|
+
}, undefined, {
|
|
19
|
+
[key: string]: {
|
|
20
|
+
[key: string]: import("tailwind-variants").ClassValue | {
|
|
21
|
+
root?: import("tailwind-variants").ClassValue;
|
|
22
|
+
thumb?: import("tailwind-variants").ClassValue;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
} | {}, {
|
|
26
|
+
root: string;
|
|
27
|
+
thumb: string;
|
|
28
|
+
}, import("tailwind-variants").TVReturnType<unknown, {
|
|
29
|
+
root: string;
|
|
30
|
+
thumb: string;
|
|
31
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
32
|
+
export type SwitchSlots = keyof ReturnType<typeof switchTheme>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { tv as e } from "tailwind-variants";
|
|
2
|
+
//#region src/theme/switch.ts
|
|
3
|
+
var t = e({ slots: {
|
|
4
|
+
root: "inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-muted",
|
|
5
|
+
thumb: "pointer-events-none block size-4 rounded-full bg-background shadow-sm transition-transform data-[state=checked]:translate-x-4.5 data-[state=unchecked]:translate-x-0.5"
|
|
6
|
+
} });
|
|
7
|
+
//#endregion
|
|
8
|
+
export { t as switchTheme };
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iryx-ui",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "Iryx â an artful Vue 3 component library built on Reka UI and Tailwind CSS v4.",
|
|
6
|
+
"author": "therok1",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/therok1/iryx-ui#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/therok1/iryx-ui.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": "https://github.com/therok1/iryx-ui/issues",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"vue",
|
|
16
|
+
"nuxt",
|
|
17
|
+
"components",
|
|
18
|
+
"component-library",
|
|
19
|
+
"reka-ui",
|
|
20
|
+
"tailwindcss",
|
|
21
|
+
"ui"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./nuxt": {
|
|
30
|
+
"types": "./dist/nuxt.d.ts",
|
|
31
|
+
"default": "./dist/nuxt.js"
|
|
32
|
+
},
|
|
33
|
+
"./theme.css": "./theme.css"
|
|
34
|
+
},
|
|
35
|
+
"module": "./dist/index.js",
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"theme.css"
|
|
40
|
+
],
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=20"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "vite build && vue-tsc -p tsconfig.build.json",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:watch": "vitest",
|
|
48
|
+
"typecheck": "vue-tsc --noEmit"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"vue": "^3.5.0"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@nuxt/kit": "^4.4.8",
|
|
55
|
+
"lucide-vue-next": "^1.0.0",
|
|
56
|
+
"reka-ui": "^2.9.10",
|
|
57
|
+
"tailwind-merge": "^3.6.0",
|
|
58
|
+
"tailwind-variants": "^3.2.2"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@vitejs/plugin-vue": "^6.0.7",
|
|
62
|
+
"@vue/test-utils": "^2.4.11",
|
|
63
|
+
"happy-dom": "^20.10.2",
|
|
64
|
+
"typescript": "^6.0.3",
|
|
65
|
+
"vite": "^8.0.16",
|
|
66
|
+
"vitest": "^4.1.8",
|
|
67
|
+
"vue": "^3.5.35",
|
|
68
|
+
"vue-tsc": "^3.3.4"
|
|
69
|
+
}
|
|
70
|
+
}
|
package/theme.css
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Iryx UI â Tailwind CSS v4 theme entry.
|
|
3
|
+
*
|
|
4
|
+
* Usage (in your app's main CSS, after Tailwind itself):
|
|
5
|
+
*
|
|
6
|
+
* @import "tailwindcss";
|
|
7
|
+
* @import "iryx-ui/theme.css";
|
|
8
|
+
*
|
|
9
|
+
* The @source directive lets your Tailwind build scan Iryx UI's published
|
|
10
|
+
* files for utility classes.
|
|
11
|
+
*
|
|
12
|
+
* Tokens are plain CSS variables, so they can be changed at runtime:
|
|
13
|
+
* override them in your own `:root` / `.dark` blocks, or call
|
|
14
|
+
* `applyTheme()` from JS. Dark mode is class-based â add `.dark` to <html>
|
|
15
|
+
* (the `useAppearance()` composable does this for you).
|
|
16
|
+
*/
|
|
17
|
+
@source "./dist";
|
|
18
|
+
|
|
19
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
20
|
+
|
|
21
|
+
:root {
|
|
22
|
+
/* Neutral surfaces â shadcn/ui "zinc" palette. */
|
|
23
|
+
--iryx-background: oklch(1 0 0);
|
|
24
|
+
--iryx-foreground: oklch(0.145 0 0);
|
|
25
|
+
--iryx-accent: oklch(0.97 0 0);
|
|
26
|
+
--iryx-accent-foreground: oklch(0.205 0 0);
|
|
27
|
+
--iryx-muted: oklch(0.97 0 0);
|
|
28
|
+
--iryx-muted-foreground: oklch(0.556 0 0);
|
|
29
|
+
--iryx-border: oklch(0.922 0 0);
|
|
30
|
+
/* Brand primary â kept as a violet gradient. */
|
|
31
|
+
--iryx-primary: oklch(0.59 0.2 277.19);
|
|
32
|
+
--iryx-primary-foreground: oklch(0.985 0.005 248);
|
|
33
|
+
--iryx-primary-from: oklch(0.59 0.2 277.19);
|
|
34
|
+
--iryx-primary-to: oklch(0.51 0.23 276.99);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.dark {
|
|
38
|
+
/* Neutral surfaces â shadcn/ui "zinc" palette. */
|
|
39
|
+
--iryx-background: oklch(0.145 0 0);
|
|
40
|
+
--iryx-foreground: oklch(0.985 0 0);
|
|
41
|
+
--iryx-accent: oklch(0.269 0 0);
|
|
42
|
+
--iryx-accent-foreground: oklch(0.985 0 0);
|
|
43
|
+
--iryx-muted: oklch(0.269 0 0);
|
|
44
|
+
--iryx-muted-foreground: oklch(0.708 0 0);
|
|
45
|
+
--iryx-border: oklch(1 0 0 / 10%);
|
|
46
|
+
/* Brand primary â kept as a violet gradient. */
|
|
47
|
+
--iryx-primary: oklch(0.62 0.22 293);
|
|
48
|
+
--iryx-primary-foreground: oklch(0.985 0.005 248);
|
|
49
|
+
--iryx-primary-from: oklch(0.62 0.22 293);
|
|
50
|
+
--iryx-primary-to: oklch(0.54 0.24 293);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@theme inline {
|
|
54
|
+
--color-background: var(--iryx-background);
|
|
55
|
+
--color-foreground: var(--iryx-foreground);
|
|
56
|
+
--color-primary: var(--iryx-primary);
|
|
57
|
+
--color-primary-foreground: var(--iryx-primary-foreground);
|
|
58
|
+
--color-primary-from: var(--iryx-primary-from);
|
|
59
|
+
--color-primary-to: var(--iryx-primary-to);
|
|
60
|
+
--color-accent: var(--iryx-accent);
|
|
61
|
+
--color-accent-foreground: var(--iryx-accent-foreground);
|
|
62
|
+
--color-muted: var(--iryx-muted);
|
|
63
|
+
--color-muted-foreground: var(--iryx-muted-foreground);
|
|
64
|
+
--color-border: var(--iryx-border);
|
|
65
|
+
}
|