@sigx/lynx-daisyui 0.1.3 → 0.4.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/README.md +109 -0
- package/dist/buttons/Button.js +53 -0
- package/dist/data/Avatar.js +46 -0
- package/dist/feedback/Alert.js +13 -0
- package/dist/feedback/Badge.js +17 -0
- package/dist/feedback/Loading.js +16 -0
- package/dist/feedback/Modal.js +23 -0
- package/dist/feedback/Progress.js +17 -0
- package/dist/feedback/Skeleton.js +18 -0
- package/dist/feedback/Steps.js +16 -0
- package/dist/forms/Checkbox.js +32 -0
- package/dist/forms/FormField.js +5 -0
- package/dist/forms/Input.js +25 -0
- package/dist/forms/Radio.js +28 -0
- package/dist/forms/Select.js +33 -0
- package/dist/forms/Textarea.js +31 -0
- package/dist/forms/Toggle.js +32 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +38 -552
- package/dist/layout/Card.js +39 -0
- package/dist/layout/Center.d.ts +2 -1
- package/dist/layout/Center.js +24 -0
- package/dist/layout/Col.d.ts +2 -2
- package/dist/layout/Col.js +33 -0
- package/dist/layout/Divider.js +27 -0
- package/dist/layout/Row.d.ts +2 -2
- package/dist/layout/Row.js +33 -0
- package/dist/layout/ScrollView.js +18 -0
- package/dist/layout/Spacer.js +11 -0
- package/dist/navigation/NavHeader.d.ts +32 -0
- package/dist/navigation/NavHeader.js +62 -0
- package/dist/navigation/NavTabBar.d.ts +36 -0
- package/dist/navigation/NavTabBar.js +58 -0
- package/dist/navigation/Tabs.js +18 -0
- package/dist/preset/index.js +66 -26
- package/dist/shared/press.d.ts +2 -0
- package/dist/shared/press.js +6 -0
- package/dist/shared/styles.d.ts +29 -1
- package/dist/shared/styles.js +90 -0
- package/dist/styles/index.css.d.ts +7 -0
- package/dist/theme/ThemeProvider.d.ts +82 -0
- package/dist/theme/ThemeProvider.js +83 -0
- package/dist/typography/Heading.js +19 -0
- package/dist/typography/Text.d.ts +11 -1
- package/dist/typography/Text.js +25 -0
- package/package.json +18 -9
- package/dist/index.js.map +0 -1
- package/dist/preset/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -42,6 +42,115 @@ import { daisyuiPreset } from '@sigx/lynx-daisyui/preset';
|
|
|
42
42
|
export default { presets: [daisyuiPreset], /* … */ };
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
The preset also publishes a `.flex-fill` utility class (long-form
|
|
46
|
+
`flex-grow/shrink/basis: 0` + `display: flex; flexDirection: column`).
|
|
47
|
+
Use it instead of `flex-1` when a Lynx parent's height comes from
|
|
48
|
+
flex rather than an explicit percentage — `flex-1` expands to
|
|
49
|
+
`flex: 1 1 auto`, which sizes to content and collapses the chain.
|
|
50
|
+
|
|
51
|
+
## Theme switching
|
|
52
|
+
|
|
53
|
+
The stylesheet ships two color themes (`daisy-light`, `daisy-dark`)
|
|
54
|
+
plus style-modifier themes (`daisy-rounded`, `daisy-flat`). Each is a
|
|
55
|
+
CSS class containing scoped `--color-*` / `--radius-*` variables; Lynx
|
|
56
|
+
has `enableCSSInheritance: true` in its layout-pipeline defaults so
|
|
57
|
+
the variables propagate to every descendant of an element with the
|
|
58
|
+
theme class.
|
|
59
|
+
|
|
60
|
+
`<ThemeProvider>` is a small wrapper that applies the active theme
|
|
61
|
+
class to a host view and exposes a controller via `useTheme()`:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { ThemeProvider, useTheme } from '@sigx/lynx-daisyui';
|
|
65
|
+
|
|
66
|
+
defineApp(() => () => (
|
|
67
|
+
<ThemeProvider initial="daisy-light">
|
|
68
|
+
<App />
|
|
69
|
+
</ThemeProvider>
|
|
70
|
+
));
|
|
71
|
+
|
|
72
|
+
// Anywhere inside:
|
|
73
|
+
const theme = useTheme();
|
|
74
|
+
theme.toggle(); // daisy-light ↔ daisy-dark
|
|
75
|
+
theme.set('daisy-dark'); // explicit
|
|
76
|
+
theme.name; // 'daisy-light' | 'daisy-dark' | custom string
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The provider's host view defaults to flex-fill long-form so it doesn't
|
|
80
|
+
collapse between a flex parent (`<SafeAreaProvider>`) and a flex child
|
|
81
|
+
(`<SafeAreaView>`). Override via `style={…}` if you want a different
|
|
82
|
+
layout role. For multi-class compositions (color + modifier),
|
|
83
|
+
`theme.set('daisy-light daisy-rounded')` works — the class string is
|
|
84
|
+
applied verbatim to the host view.
|
|
85
|
+
|
|
86
|
+
## Navigation chrome
|
|
87
|
+
|
|
88
|
+
Two daisy-themed components that pair with
|
|
89
|
+
[`@sigx/lynx-navigation`](../lynx-navigation). Both read state via the
|
|
90
|
+
navigation package's hooks (no internal-module imports), so swapping
|
|
91
|
+
in custom designs later is a one-component change.
|
|
92
|
+
|
|
93
|
+
### `<NavTabBar />`
|
|
94
|
+
|
|
95
|
+
Themed bottom tab bar. Drop it inside `<Tabs>` and it picks up the
|
|
96
|
+
active tab + tab list via `useTabs()`.
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { Tabs } from '@sigx/lynx-navigation';
|
|
100
|
+
import { NavTabBar } from '@sigx/lynx-daisyui';
|
|
101
|
+
|
|
102
|
+
<Tabs initialTab="trips">
|
|
103
|
+
<Tabs.Screen name="trips" label="Trips">…</Tabs.Screen>
|
|
104
|
+
<Tabs.Screen name="map" label="Map">…</Tabs.Screen>
|
|
105
|
+
<NavTabBar />
|
|
106
|
+
</Tabs>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
| Prop | Default | Notes |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `position` | `'bottom'` | `'top'` flips the separator border to the bottom edge. |
|
|
112
|
+
| `background` | `'base-200'` | `'base-100' / 'base-200' / 'base-300' / 'transparent'`. |
|
|
113
|
+
| `bordered` | `true` | Show a 1px separator on the edge opposite `position`. |
|
|
114
|
+
| `renderTab` | — | `(info, ctx) => JSX` — replace per-tab rendering entirely. |
|
|
115
|
+
|
|
116
|
+
### `<NavHeader />`
|
|
117
|
+
|
|
118
|
+
Themed header bar. Drop it inside a `<Stack>` (uses the Stack's
|
|
119
|
+
default slot, introduced in `@sigx/lynx-navigation` 1.0) so its
|
|
120
|
+
`useNav()` resolves to the per-stack nav:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { Stack } from '@sigx/lynx-navigation';
|
|
124
|
+
import { NavHeader } from '@sigx/lynx-daisyui';
|
|
125
|
+
|
|
126
|
+
<Stack initialRoute="tripsHome">
|
|
127
|
+
<NavHeader />
|
|
128
|
+
</Stack>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Reads everything it needs via `useScreenChrome()` — title, header-
|
|
132
|
+
shown, back-button visibility, and the screen's left/right slot fills.
|
|
133
|
+
Renders an ~48dp horizontal bar with the title centred, a "‹ Back"
|
|
134
|
+
button on the left when `canGoBack`, and the right slot flush-right.
|
|
135
|
+
|
|
136
|
+
| Prop | Default | Notes |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| `background` | `'base-200'` | Same colour tokens as `NavTabBar`. |
|
|
139
|
+
| `bordered` | `true` | Bottom separator line. |
|
|
140
|
+
| `renderBack` | — | `({ pop }) => JSX` — replace the default back button. |
|
|
141
|
+
|
|
142
|
+
For a fully-custom design, build directly on
|
|
143
|
+
`useScreenChrome()` from `@sigx/lynx-navigation` — `NavHeader` is just
|
|
144
|
+
one consumer of that hook.
|
|
145
|
+
|
|
146
|
+
## Layout primitives
|
|
147
|
+
|
|
148
|
+
Daisy's flex primitives (`Center`, `Col`, `Row`) accept a `flex={n}`
|
|
149
|
+
prop. The preset rewrites that into the long-form `flex-grow/shrink/
|
|
150
|
+
basis: 0` triple, so `flex={1}` actually fills available space instead
|
|
151
|
+
of collapsing to content size — the standard Lynx `flex: 1` shorthand
|
|
152
|
+
expands to `flex: 1 1 auto` which doesn't do what most people expect.
|
|
153
|
+
|
|
45
154
|
## Status
|
|
46
155
|
|
|
47
156
|
Initial release — APIs may shift as the Lynx styling story evolves.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
import { Pressable } from '@sigx/lynx-gestures';
|
|
4
|
+
import { Loading } from '../feedback/Loading.js';
|
|
5
|
+
import { PRESSED_SCALE, PRESSED_OPACITY } from '../shared/press.js';
|
|
6
|
+
const variantClasses = {
|
|
7
|
+
primary: 'btn-primary', secondary: 'btn-secondary', accent: 'btn-accent',
|
|
8
|
+
info: 'btn-info', success: 'btn-success', warning: 'btn-warning',
|
|
9
|
+
error: 'btn-error', ghost: 'btn-ghost', link: 'btn-link', neutral: 'btn-neutral',
|
|
10
|
+
};
|
|
11
|
+
const sizeClasses = {
|
|
12
|
+
xs: 'btn-xs', sm: 'btn-sm', md: '', lg: 'btn-lg', xl: 'btn-xl',
|
|
13
|
+
};
|
|
14
|
+
export const Button = component(({ props, slots, emit }) => {
|
|
15
|
+
const getClasses = () => {
|
|
16
|
+
const c = ['btn'];
|
|
17
|
+
if (props.variant)
|
|
18
|
+
c.push(variantClasses[props.variant]);
|
|
19
|
+
if (props.size) {
|
|
20
|
+
const s = sizeClasses[props.size];
|
|
21
|
+
if (s)
|
|
22
|
+
c.push(s);
|
|
23
|
+
}
|
|
24
|
+
if (props.outline)
|
|
25
|
+
c.push('btn-outline');
|
|
26
|
+
if (props.soft)
|
|
27
|
+
c.push('btn-soft');
|
|
28
|
+
if (props.wide)
|
|
29
|
+
c.push('btn-wide');
|
|
30
|
+
if (props.loading)
|
|
31
|
+
c.push('btn-loading');
|
|
32
|
+
if (props.block)
|
|
33
|
+
c.push('btn-block');
|
|
34
|
+
if (props.circle)
|
|
35
|
+
c.push('btn-circle');
|
|
36
|
+
if (props.square)
|
|
37
|
+
c.push('btn-square');
|
|
38
|
+
if (props.active)
|
|
39
|
+
c.push('btn-active');
|
|
40
|
+
if (props.disabled)
|
|
41
|
+
c.push('btn-disabled');
|
|
42
|
+
if (props.class)
|
|
43
|
+
c.push(props.class);
|
|
44
|
+
return c.join(' ');
|
|
45
|
+
};
|
|
46
|
+
return () => {
|
|
47
|
+
const inert = !!(props.disabled || props.loading);
|
|
48
|
+
return (_jsx(Pressable, { class: getClasses(), disabled: inert, pressedScale: PRESSED_SCALE, pressedOpacity: PRESSED_OPACITY, longPressDuration: 0, onPress: () => { if (!inert)
|
|
49
|
+
emit('press'); }, children: props.loading
|
|
50
|
+
? _jsx(Loading, { type: "spinner", size: "sm" })
|
|
51
|
+
: slots.default?.() }));
|
|
52
|
+
};
|
|
53
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
const sizeMap = {
|
|
4
|
+
xs: 24,
|
|
5
|
+
sm: 32,
|
|
6
|
+
md: 48,
|
|
7
|
+
lg: 64,
|
|
8
|
+
xl: 96,
|
|
9
|
+
};
|
|
10
|
+
const fontSizeMap = {
|
|
11
|
+
xs: 10,
|
|
12
|
+
sm: 12,
|
|
13
|
+
md: 18,
|
|
14
|
+
lg: 24,
|
|
15
|
+
xl: 36,
|
|
16
|
+
};
|
|
17
|
+
export const Avatar = component(({ props }) => {
|
|
18
|
+
return () => {
|
|
19
|
+
const size = props.size || 'md';
|
|
20
|
+
const dim = sizeMap[size];
|
|
21
|
+
const classes = ['avatar'];
|
|
22
|
+
if (props.online)
|
|
23
|
+
classes.push('online');
|
|
24
|
+
if (props.offline)
|
|
25
|
+
classes.push('offline');
|
|
26
|
+
if (props.placeholder && !props.src)
|
|
27
|
+
classes.push('placeholder');
|
|
28
|
+
if (props.class)
|
|
29
|
+
classes.push(props.class);
|
|
30
|
+
const rounded = props.rounded;
|
|
31
|
+
const borderRadius = rounded === 'full' || rounded === true ? dim / 2 : 8;
|
|
32
|
+
const innerStyle = {
|
|
33
|
+
width: dim,
|
|
34
|
+
height: dim,
|
|
35
|
+
borderRadius,
|
|
36
|
+
overflow: 'hidden',
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
justifyContent: 'center',
|
|
39
|
+
display: 'flex',
|
|
40
|
+
};
|
|
41
|
+
if (props.src) {
|
|
42
|
+
return (_jsx("view", { class: classes.join(' '), children: _jsx("view", { style: innerStyle, children: _jsx("image", { src: props.src, style: { width: dim, height: dim, borderRadius } }) }) }));
|
|
43
|
+
}
|
|
44
|
+
return (_jsx("view", { class: classes.join(' '), children: _jsx("view", { class: "avatar-placeholder", style: innerStyle, children: _jsx("text", { style: { fontSize: fontSizeMap[size] }, children: props.placeholder || '?' }) }) }));
|
|
45
|
+
};
|
|
46
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
export const Alert = component(({ props, slots }) => {
|
|
4
|
+
const getClasses = () => {
|
|
5
|
+
const c = ['alert'];
|
|
6
|
+
if (props.variant)
|
|
7
|
+
c.push(`alert-${props.variant}`);
|
|
8
|
+
if (props.class)
|
|
9
|
+
c.push(props.class);
|
|
10
|
+
return c.join(' ');
|
|
11
|
+
};
|
|
12
|
+
return () => _jsx("view", { class: getClasses(), children: slots.default?.() });
|
|
13
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
export const Badge = component(({ props, slots }) => {
|
|
4
|
+
const getClasses = () => {
|
|
5
|
+
const c = ['badge'];
|
|
6
|
+
if (props.variant)
|
|
7
|
+
c.push(`badge-${props.variant}`);
|
|
8
|
+
if (props.size)
|
|
9
|
+
c.push(`badge-${props.size}`);
|
|
10
|
+
if (props.outline)
|
|
11
|
+
c.push('badge-outline');
|
|
12
|
+
if (props.class)
|
|
13
|
+
c.push(props.class);
|
|
14
|
+
return c.join(' ');
|
|
15
|
+
};
|
|
16
|
+
return () => _jsx("view", { class: getClasses(), children: slots.default?.() });
|
|
17
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
export const Loading = component(({ props }) => {
|
|
4
|
+
const getClasses = () => {
|
|
5
|
+
const c = ['loading'];
|
|
6
|
+
c.push(`loading-${props.type ?? 'spinner'}`);
|
|
7
|
+
if (props.size)
|
|
8
|
+
c.push(`loading-${props.size}`);
|
|
9
|
+
if (props.color)
|
|
10
|
+
c.push(`text-${props.color}`);
|
|
11
|
+
if (props.class)
|
|
12
|
+
c.push(props.class);
|
|
13
|
+
return c.join(' ');
|
|
14
|
+
};
|
|
15
|
+
return () => _jsx("view", { class: getClasses() });
|
|
16
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component, compound } from '@sigx/lynx';
|
|
3
|
+
const _Modal = component(({ props, slots }) => {
|
|
4
|
+
return () => {
|
|
5
|
+
if (!props.open)
|
|
6
|
+
return _jsx("view", { style: { display: 'none' } });
|
|
7
|
+
return (_jsx("view", { class: "modal-overlay", bindtap: () => { props.onClose?.(); }, children: _jsx("view", { class: `modal-box${props.class ? ' ' + props.class : ''}`, bindtap: (e) => { e?.stopPropagation?.(); }, children: slots.default?.() }) }));
|
|
8
|
+
};
|
|
9
|
+
});
|
|
10
|
+
const ModalHeader = component(({ props, slots }) => {
|
|
11
|
+
return () => (_jsx("view", { class: `modal-header${props.class ? ' ' + props.class : ''}`, children: slots.default?.() }));
|
|
12
|
+
});
|
|
13
|
+
const ModalBody = component(({ props, slots }) => {
|
|
14
|
+
return () => (_jsx("view", { class: `modal-body${props.class ? ' ' + props.class : ''}`, children: slots.default?.() }));
|
|
15
|
+
});
|
|
16
|
+
const ModalActions = component(({ props, slots }) => {
|
|
17
|
+
return () => (_jsx("view", { class: `modal-action${props.class ? ' ' + props.class : ''}`, children: slots.default?.() }));
|
|
18
|
+
});
|
|
19
|
+
export const Modal = compound(_Modal, {
|
|
20
|
+
Header: ModalHeader,
|
|
21
|
+
Body: ModalBody,
|
|
22
|
+
Actions: ModalActions,
|
|
23
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
export const Progress = component(({ props }) => {
|
|
4
|
+
const getClasses = () => {
|
|
5
|
+
const c = ['progress'];
|
|
6
|
+
if (props.color)
|
|
7
|
+
c.push(`progress-${props.color}`);
|
|
8
|
+
if (props.class)
|
|
9
|
+
c.push(props.class);
|
|
10
|
+
return c.join(' ');
|
|
11
|
+
};
|
|
12
|
+
return () => {
|
|
13
|
+
const max = props.max ?? 100;
|
|
14
|
+
const pct = Math.min(Math.max((props.value ?? 0) / max, 0), 1) * 100;
|
|
15
|
+
return (_jsx("view", { class: getClasses(), children: _jsx("view", { class: "progress-bar", style: { width: `${pct}%` } }) }));
|
|
16
|
+
};
|
|
17
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
export const Skeleton = component(({ props }) => {
|
|
4
|
+
return () => {
|
|
5
|
+
const style = {};
|
|
6
|
+
if (props.width != null)
|
|
7
|
+
style.width = props.width;
|
|
8
|
+
if (props.height != null)
|
|
9
|
+
style.height = props.height;
|
|
10
|
+
if (props.circle) {
|
|
11
|
+
const size = props.width ?? props.height ?? 48;
|
|
12
|
+
style.width = size;
|
|
13
|
+
style.height = size;
|
|
14
|
+
style.borderRadius = typeof size === 'number' ? size / 2 : '50%';
|
|
15
|
+
}
|
|
16
|
+
return (_jsx("view", { class: `skeleton${props.class ? ' ' + props.class : ''}`, style: style }));
|
|
17
|
+
};
|
|
18
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component, compound } from '@sigx/lynx';
|
|
3
|
+
const _Steps = component(({ props, slots }) => {
|
|
4
|
+
return () => {
|
|
5
|
+
const isVertical = props.vertical ?? false;
|
|
6
|
+
return (_jsx("view", { class: `steps${isVertical ? ' steps-vertical' : ' steps-horizontal'}${props.class ? ' ' + props.class : ''}`, children: slots.default?.() }));
|
|
7
|
+
};
|
|
8
|
+
});
|
|
9
|
+
const Step = component(({ props, slots }) => {
|
|
10
|
+
return () => {
|
|
11
|
+
const color = props.color;
|
|
12
|
+
const colorClass = color ? ` step-${color}` : '';
|
|
13
|
+
return (_jsxs("view", { class: `step${colorClass}${props.class ? ' ' + props.class : ''}`, children: [_jsx("view", { class: `step-indicator${colorClass}`, children: props.content ? _jsx("text", { style: { fontSize: 14 }, children: props.content }) : null }), slots.default?.()] }));
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
export const Steps = compound(_Steps, { Step });
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
import { Pressable } from '@sigx/lynx-gestures';
|
|
4
|
+
import { PRESSED_SCALE, PRESSED_OPACITY } from '../shared/press.js';
|
|
5
|
+
const checkmarkSizeMap = {
|
|
6
|
+
xs: 10, sm: 12, md: 14, lg: 19,
|
|
7
|
+
};
|
|
8
|
+
export const Checkbox = component(({ props, emit }) => {
|
|
9
|
+
const getClasses = () => {
|
|
10
|
+
const c = ['checkbox'];
|
|
11
|
+
const size = props.size ?? 'md';
|
|
12
|
+
if (size !== 'md')
|
|
13
|
+
c.push(`checkbox-${size}`);
|
|
14
|
+
if (props.color)
|
|
15
|
+
c.push(`checkbox-${props.color}`);
|
|
16
|
+
if (props.checked)
|
|
17
|
+
c.push('checkbox-checked');
|
|
18
|
+
if (props.disabled)
|
|
19
|
+
c.push('checkbox-disabled');
|
|
20
|
+
if (props.class)
|
|
21
|
+
c.push(props.class);
|
|
22
|
+
return c.join(' ');
|
|
23
|
+
};
|
|
24
|
+
return () => {
|
|
25
|
+
const checked = !!props.checked;
|
|
26
|
+
const size = props.size ?? 'md';
|
|
27
|
+
return (_jsx(Pressable, { class: getClasses(), disabled: !!props.disabled, pressedScale: PRESSED_SCALE, pressedOpacity: PRESSED_OPACITY, longPressDuration: 0, onPress: () => {
|
|
28
|
+
if (!props.disabled)
|
|
29
|
+
emit('change', !checked);
|
|
30
|
+
}, children: checked ? (_jsx("text", { class: "checkbox-mark", style: { fontSize: checkmarkSizeMap[size] }, children: "\u2713" })) : null }));
|
|
31
|
+
};
|
|
32
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
export const FormField = component(({ props, slots }) => {
|
|
4
|
+
return () => (_jsxs("view", { class: ['form-control', props.class].filter(Boolean).join(' '), style: { gap: 4 }, children: [props.label && (_jsx("view", { class: "label", children: _jsx("text", { class: "label-text", children: props.required ? `${props.label} *` : props.label }) })), slots.default?.(), props.error && (_jsx("view", { class: "label", children: _jsx("text", { class: "label-text-error", children: props.error }) }))] }));
|
|
5
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
const sizeClasses = {
|
|
4
|
+
xs: 'input-xs', sm: 'input-sm', md: '', lg: 'input-lg',
|
|
5
|
+
};
|
|
6
|
+
export const Input = component(({ props }) => {
|
|
7
|
+
const getClasses = () => {
|
|
8
|
+
const c = ['input'];
|
|
9
|
+
if (props.variant === 'bordered')
|
|
10
|
+
c.push('input-bordered');
|
|
11
|
+
if (props.variant === 'ghost')
|
|
12
|
+
c.push('input-ghost');
|
|
13
|
+
if (props.color)
|
|
14
|
+
c.push(`input-${props.color}`);
|
|
15
|
+
if (props.size) {
|
|
16
|
+
const s = sizeClasses[props.size];
|
|
17
|
+
if (s)
|
|
18
|
+
c.push(s);
|
|
19
|
+
}
|
|
20
|
+
if (props.class)
|
|
21
|
+
c.push(props.class);
|
|
22
|
+
return c.join(' ');
|
|
23
|
+
};
|
|
24
|
+
return () => (_jsx("input", { class: getClasses(), placeholder: props.placeholder, type: props.type ?? 'text', disabled: props.disabled, model: props.model }));
|
|
25
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component, compound } from '@sigx/lynx';
|
|
3
|
+
import { Pressable } from '@sigx/lynx-gestures';
|
|
4
|
+
import { PRESSED_SCALE, PRESSED_OPACITY } from '../shared/press.js';
|
|
5
|
+
const RadioItem = component(({ props, emit }) => {
|
|
6
|
+
const getClasses = () => {
|
|
7
|
+
const c = ['radio'];
|
|
8
|
+
if (props.color)
|
|
9
|
+
c.push(`radio-${props.color}`);
|
|
10
|
+
if (props.size)
|
|
11
|
+
c.push(`radio-${props.size}`);
|
|
12
|
+
if (props.checked)
|
|
13
|
+
c.push('radio-checked');
|
|
14
|
+
if (props.class)
|
|
15
|
+
c.push(props.class);
|
|
16
|
+
return c.join(' ');
|
|
17
|
+
};
|
|
18
|
+
return () => (_jsxs(Pressable, { style: { flexDirection: 'row', alignItems: 'center', gap: 8, opacity: props.disabled ? 0.5 : 1 }, disabled: !!props.disabled, pressedScale: PRESSED_SCALE, pressedOpacity: PRESSED_OPACITY, longPressDuration: 0, onPress: () => {
|
|
19
|
+
if (!props.disabled && props.value != null)
|
|
20
|
+
emit('select', props.value);
|
|
21
|
+
}, children: [_jsx("view", { class: getClasses(), children: props.checked && _jsx("view", { class: "radio-mark" }) }), props.label && _jsx("text", { children: props.label })] }));
|
|
22
|
+
});
|
|
23
|
+
const _RadioGroup = component(({ props, slots }) => {
|
|
24
|
+
return () => (_jsx("view", { class: props.class ?? '', style: { gap: 8 }, children: slots.default?.() }));
|
|
25
|
+
});
|
|
26
|
+
export const Radio = compound(_RadioGroup, {
|
|
27
|
+
Item: RadioItem,
|
|
28
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component, signal } from '@sigx/lynx';
|
|
3
|
+
import { Pressable } from '@sigx/lynx-gestures';
|
|
4
|
+
import { PRESSED_SCALE, PRESSED_OPACITY } from '../shared/press.js';
|
|
5
|
+
export const Select = component(({ props, emit }) => {
|
|
6
|
+
const state = signal({ open: false });
|
|
7
|
+
const getClasses = () => {
|
|
8
|
+
const c = ['select'];
|
|
9
|
+
if (props.variant === 'bordered')
|
|
10
|
+
c.push('select-bordered');
|
|
11
|
+
if (props.variant === 'ghost')
|
|
12
|
+
c.push('select-ghost');
|
|
13
|
+
if (props.color)
|
|
14
|
+
c.push(`select-${props.color}`);
|
|
15
|
+
if (props.size)
|
|
16
|
+
c.push(`select-${props.size}`);
|
|
17
|
+
if (props.class)
|
|
18
|
+
c.push(props.class);
|
|
19
|
+
return c.join(' ');
|
|
20
|
+
};
|
|
21
|
+
const getSelectedLabel = () => {
|
|
22
|
+
const opts = props.options ?? [];
|
|
23
|
+
const found = opts.find((o) => o.value === props.value);
|
|
24
|
+
return found ? found.label : (props.placeholder ?? 'Select...');
|
|
25
|
+
};
|
|
26
|
+
return () => (_jsxs("view", { style: { position: 'relative', opacity: props.disabled ? 0.5 : 1 }, children: [_jsxs(Pressable, { class: getClasses(), disabled: !!props.disabled, pressedScale: PRESSED_SCALE, pressedOpacity: PRESSED_OPACITY, longPressDuration: 0, onPress: () => {
|
|
27
|
+
if (!props.disabled)
|
|
28
|
+
state.open = !state.open;
|
|
29
|
+
}, children: [_jsx("text", { children: getSelectedLabel() }), _jsx("view", { style: { marginLeft: 'auto' }, children: _jsx("text", { children: state.open ? '▲' : '▼' }) })] }), state.open && !props.disabled && (_jsx("view", { class: "select-dropdown", style: { position: 'absolute', top: '100%', left: 0, right: 0, zIndex: 10 }, children: (props.options ?? []).map((option) => (_jsx(Pressable, { class: `select-option${option.value === props.value ? ' select-option-active' : ''}`, pressedScale: PRESSED_SCALE, pressedOpacity: PRESSED_OPACITY, longPressDuration: 0, onPress: () => {
|
|
30
|
+
emit('change', option.value);
|
|
31
|
+
state.open = false;
|
|
32
|
+
}, children: _jsx("text", { children: option.label }) }))) }))] }));
|
|
33
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
const sizeClasses = {
|
|
4
|
+
xs: 'textarea-xs', sm: 'textarea-sm', md: '', lg: 'textarea-lg',
|
|
5
|
+
};
|
|
6
|
+
export const Textarea = component(({ props }) => {
|
|
7
|
+
const getClasses = () => {
|
|
8
|
+
const c = ['textarea'];
|
|
9
|
+
if (props.variant === 'bordered')
|
|
10
|
+
c.push('textarea-bordered');
|
|
11
|
+
if (props.variant === 'ghost')
|
|
12
|
+
c.push('textarea-ghost');
|
|
13
|
+
if (props.color)
|
|
14
|
+
c.push(`textarea-${props.color}`);
|
|
15
|
+
if (props.size) {
|
|
16
|
+
const s = sizeClasses[props.size];
|
|
17
|
+
if (s)
|
|
18
|
+
c.push(s);
|
|
19
|
+
}
|
|
20
|
+
if (props.class)
|
|
21
|
+
c.push(props.class);
|
|
22
|
+
return c.join(' ');
|
|
23
|
+
};
|
|
24
|
+
const getHeight = () => {
|
|
25
|
+
const rows = props.rows ?? 3;
|
|
26
|
+
const lineHeight = 20;
|
|
27
|
+
const padding = 16;
|
|
28
|
+
return rows * lineHeight + padding;
|
|
29
|
+
};
|
|
30
|
+
return () => (_jsx("textarea", { class: getClasses(), placeholder: props.placeholder, disabled: props.disabled, model: props.model, style: { height: getHeight() } }));
|
|
31
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component } from '@sigx/lynx';
|
|
3
|
+
import { Pressable } from '@sigx/lynx-gestures';
|
|
4
|
+
import { PRESSED_SCALE, PRESSED_OPACITY } from '../shared/press.js';
|
|
5
|
+
const thumbOffsetMap = {
|
|
6
|
+
xs: 10, sm: 16, md: 20, lg: 24,
|
|
7
|
+
};
|
|
8
|
+
export const Toggle = component(({ props, emit }) => {
|
|
9
|
+
const getClasses = () => {
|
|
10
|
+
const c = ['toggle'];
|
|
11
|
+
const size = props.size ?? 'md';
|
|
12
|
+
c.push(`toggle-${size}`);
|
|
13
|
+
if (props.color)
|
|
14
|
+
c.push(`toggle-${props.color}`);
|
|
15
|
+
if (props.checked)
|
|
16
|
+
c.push('toggle-checked');
|
|
17
|
+
if (props.disabled)
|
|
18
|
+
c.push('toggle-disabled');
|
|
19
|
+
if (props.class)
|
|
20
|
+
c.push(props.class);
|
|
21
|
+
return c.join(' ');
|
|
22
|
+
};
|
|
23
|
+
return () => {
|
|
24
|
+
const checked = !!props.checked;
|
|
25
|
+
const size = props.size ?? 'md';
|
|
26
|
+
const offset = checked ? thumbOffsetMap[size] : 0;
|
|
27
|
+
return (_jsx(Pressable, { class: getClasses(), disabled: !!props.disabled, pressedScale: PRESSED_SCALE, pressedOpacity: PRESSED_OPACITY, longPressDuration: 0, onPress: () => {
|
|
28
|
+
if (!props.disabled)
|
|
29
|
+
emit('change', !checked);
|
|
30
|
+
}, children: _jsx("view", { class: "toggle-thumb", style: { transform: `translateX(${offset}px)` } }) }));
|
|
31
|
+
};
|
|
32
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export { ScrollView } from './layout/ScrollView.js';
|
|
|
14
14
|
export type { ScrollViewProps } from './layout/ScrollView.js';
|
|
15
15
|
export { Divider } from './layout/Divider.js';
|
|
16
16
|
export type { DividerProps } from './layout/Divider.js';
|
|
17
|
+
export type { DaisyColor, BackgroundValue, SpacingValue, BoxProps } from './shared/styles.js';
|
|
18
|
+
export { resolveDaisyColor } from './shared/styles.js';
|
|
17
19
|
export { Input } from './forms/Input.js';
|
|
18
20
|
export type { InputProps, InputSize, InputVariant, InputColor } from './forms/Input.js';
|
|
19
21
|
export { Toggle } from './forms/Toggle.js';
|
|
@@ -44,6 +46,12 @@ export { Steps } from './feedback/Steps.js';
|
|
|
44
46
|
export type { StepsProps, StepProps, StepColor } from './feedback/Steps.js';
|
|
45
47
|
export { Tabs } from './navigation/Tabs.js';
|
|
46
48
|
export type { TabsProps, TabProps } from './navigation/Tabs.js';
|
|
49
|
+
export { NavTabBar } from './navigation/NavTabBar.js';
|
|
50
|
+
export type { NavTabBarProps, NavTabBarPosition, NavTabBarBackground, NavTabRenderContext, } from './navigation/NavTabBar.js';
|
|
51
|
+
export { NavHeader } from './navigation/NavHeader.js';
|
|
52
|
+
export type { NavHeaderProps, NavHeaderBackground, } from './navigation/NavHeader.js';
|
|
53
|
+
export { ThemeProvider, useTheme } from './theme/ThemeProvider.js';
|
|
54
|
+
export type { DaisyTheme, ThemeController, ThemeProviderProps, } from './theme/ThemeProvider.js';
|
|
47
55
|
export { Avatar } from './data/Avatar.js';
|
|
48
56
|
export type { AvatarProps, AvatarSize } from './data/Avatar.js';
|
|
49
57
|
export { Text } from './typography/Text.js';
|