@solidpb/ui-kit 0.3.0 → 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/dist/components/FileInput/FileInput.jsx +16 -1
- package/dist/components/{Form/Form.d.ts → Form.d.ts} +14 -10
- package/dist/components/{Form/Form.jsx → Form.jsx} +36 -17
- package/dist/components/Image/Image.jsx +3 -3
- package/dist/components/RelationPicker.d.ts +23 -0
- package/dist/components/RelationPicker.jsx +144 -0
- package/dist/components/Select/Select.jsx +13 -9
- package/dist/components/Table/Table.jsx +1 -1
- package/dist/components/ThemeSwitch/ThemeSwitch.jsx +5 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
- package/dist/components/Form/index.d.ts +0 -1
- package/dist/components/Form/index.js +0 -1
- /package/dist/components/{Form/formContext.d.ts → formContext.d.ts} +0 -0
- /package/dist/components/{Form/formContext.js → formContext.js} +0 -0
|
@@ -28,6 +28,21 @@ const input = tv({
|
|
|
28
28
|
size: "sm",
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
|
+
const label = tv({
|
|
32
|
+
base: "label text-xs",
|
|
33
|
+
variants: {
|
|
34
|
+
size: {
|
|
35
|
+
xs: "text-xs",
|
|
36
|
+
sm: "text-xs",
|
|
37
|
+
md: "text-xs",
|
|
38
|
+
lg: "text-sm",
|
|
39
|
+
xl: "text-sm",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
defaultVariants: {
|
|
43
|
+
size: "sm",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
31
46
|
export const FileInput = (props) => {
|
|
32
47
|
const [local, others] = splitProps(props, ["label", "class", "onChange", "saveFunc"]);
|
|
33
48
|
const handleChange = (files) => {
|
|
@@ -36,7 +51,7 @@ export const FileInput = (props) => {
|
|
|
36
51
|
};
|
|
37
52
|
return (<label class="flex flex-col gap-1 w-fit">
|
|
38
53
|
<Show when={local.label}>
|
|
39
|
-
<span class=
|
|
54
|
+
<span class={label({ size: props.size })}>{local.label}</span>
|
|
40
55
|
</Show>
|
|
41
56
|
<input {...others} type="file" class={input({ class: local.class })} accept={props.accept} multiple={props.multiple} onChange={(e) => handleChange(e.currentTarget.files)}/>
|
|
42
57
|
</label>);
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { JSXElement } from "solid-js";
|
|
2
|
-
import { type SwitchProps } from "
|
|
3
|
-
import { type SelectProps } from "
|
|
4
|
-
import { type InputRootProps } from "
|
|
5
|
-
import { type TextAreaRootProps } from "
|
|
6
|
-
import { type CheckboxProps } from "
|
|
7
|
-
import { type NumberInputRootProps } from "
|
|
8
|
-
import { type SliderProps } from "
|
|
9
|
-
import { type ImageProps } from "
|
|
10
|
-
import { type FileInputProps } from "
|
|
2
|
+
import { type SwitchProps } from "./Switch";
|
|
3
|
+
import { type SelectProps } from "./Select";
|
|
4
|
+
import { type InputRootProps } from "./Input";
|
|
5
|
+
import { type TextAreaRootProps } from "./TextArea";
|
|
6
|
+
import { type CheckboxProps } from "./Checkbox";
|
|
7
|
+
import { type NumberInputRootProps } from "./NumberInput";
|
|
8
|
+
import { type SliderProps } from "./Slider";
|
|
9
|
+
import { type ImageProps } from "./Image";
|
|
10
|
+
import { type FileInputProps } from "./FileInput";
|
|
11
|
+
import { RelationPickerProps } from "./RelationPicker";
|
|
11
12
|
export interface FormProps<T> {
|
|
12
|
-
data: T
|
|
13
|
+
data: Partial<T>;
|
|
13
14
|
title?: string;
|
|
14
15
|
onSave?: (values: Partial<T>) => Promise<void>;
|
|
15
16
|
onCancel?: () => void;
|
|
@@ -33,5 +34,8 @@ export declare function createForm<T>(): {
|
|
|
33
34
|
FileField: (props: FileInputProps & BaseFieldProps<T>) => import("solid-js").JSX.Element;
|
|
34
35
|
ImageField: (props: ImageProps & BaseFieldProps<T>) => import("solid-js").JSX.Element;
|
|
35
36
|
SliderField: (props: SliderProps & BaseFieldProps<T>) => import("solid-js").JSX.Element;
|
|
37
|
+
RelationField: <K extends {
|
|
38
|
+
id: string;
|
|
39
|
+
}>(props: RelationPickerProps<K> & BaseFieldProps<T>) => import("solid-js").JSX.Element;
|
|
36
40
|
};
|
|
37
41
|
export {};
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { splitProps } from "solid-js";
|
|
2
2
|
import { createStore } from "solid-js/store";
|
|
3
|
-
import { InternalFormContext, useInternalFormContext } from "./formContext";
|
|
4
|
-
import { Switch } from "../Switch";
|
|
5
|
-
import { Select } from "../Select";
|
|
6
|
-
import { Input } from "../Input";
|
|
7
|
-
import { TextArea } from "../TextArea";
|
|
8
|
-
import { Checkbox } from "../Checkbox";
|
|
9
|
-
import { NumberInput } from "../NumberInput";
|
|
10
|
-
import { Slider } from "../Slider";
|
|
11
|
-
import { Image } from "../Image";
|
|
12
|
-
import { Button } from "../Button";
|
|
13
|
-
import { FileInput } from "../FileInput";
|
|
14
3
|
import { tv } from "tailwind-variants";
|
|
4
|
+
import { InternalFormContext, useInternalFormContext } from "./formContext";
|
|
5
|
+
import { Switch } from "./Switch";
|
|
6
|
+
import { Select } from "./Select";
|
|
7
|
+
import { Input } from "./Input";
|
|
8
|
+
import { TextArea } from "./TextArea";
|
|
9
|
+
import { Checkbox } from "./Checkbox";
|
|
10
|
+
import { NumberInput } from "./NumberInput";
|
|
11
|
+
import { Slider } from "./Slider";
|
|
12
|
+
import { Image } from "./Image";
|
|
13
|
+
import { Button } from "./Button";
|
|
14
|
+
import { FileInput } from "./FileInput";
|
|
15
|
+
import RelationPicker from "./RelationPicker";
|
|
15
16
|
const formClass = tv({
|
|
16
17
|
base: "space-y-4 space-x-4",
|
|
17
18
|
});
|
|
@@ -24,7 +25,7 @@ export function createForm() {
|
|
|
24
25
|
const getValue = (key) => {
|
|
25
26
|
return values[key];
|
|
26
27
|
};
|
|
27
|
-
const contextValue = { setValue, getValue
|
|
28
|
+
const contextValue = { setValue, getValue };
|
|
28
29
|
const handleSubmit = (e) => {
|
|
29
30
|
e.preventDefault();
|
|
30
31
|
props.onSave?.(values);
|
|
@@ -36,10 +37,10 @@ export function createForm() {
|
|
|
36
37
|
{props.children}
|
|
37
38
|
|
|
38
39
|
<div class="flex justify-end gap-2">
|
|
39
|
-
{props.onCancel && (<Button appearance="neutral" onClick={props.onCancel}
|
|
40
|
+
{props.onCancel && (<Button appearance="neutral" onClick={props.onCancel}>
|
|
40
41
|
Cancel
|
|
41
42
|
</Button>)}
|
|
42
|
-
{props.onSave && (<Button appearance="success" type="submit"
|
|
43
|
+
{props.onSave && (<Button appearance="success" type="submit">
|
|
43
44
|
Save
|
|
44
45
|
</Button>)}
|
|
45
46
|
</div>
|
|
@@ -80,15 +81,32 @@ export function createForm() {
|
|
|
80
81
|
};
|
|
81
82
|
const ImageField = (props) => {
|
|
82
83
|
const form = useInternalFormContext();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
const [local, others] = splitProps(props, ["onChange"]);
|
|
85
|
+
// have to set src manually, when using with pocketbase, the value will be a URL string,
|
|
86
|
+
// but when uploading a new file it will be a File object, so we need to handle both cases
|
|
87
|
+
return (<Image editable {...others} onChange={(file) => {
|
|
88
|
+
form.setValue(props.field, file);
|
|
89
|
+
local.onChange?.(file);
|
|
86
90
|
}}/>);
|
|
87
91
|
};
|
|
88
92
|
const SliderField = (props) => {
|
|
89
93
|
const form = useInternalFormContext();
|
|
90
94
|
return (<Slider {...props} value={form.getValue(props.field)} onChange={(v) => form.setValue(props.field, v)}/>);
|
|
91
95
|
};
|
|
96
|
+
const RelationField = (props) => {
|
|
97
|
+
const form = useInternalFormContext();
|
|
98
|
+
const [local, others] = splitProps(props, ["onChange"]);
|
|
99
|
+
const handleChange = (val) => {
|
|
100
|
+
if (props.multi) {
|
|
101
|
+
form.setValue(props.field, (Array.isArray(val) ? val.map((v) => v.id) : []));
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
form.setValue(props.field, (val?.id || null));
|
|
105
|
+
}
|
|
106
|
+
local.onChange?.(val);
|
|
107
|
+
};
|
|
108
|
+
return <RelationPicker {...others} onChange={handleChange}/>;
|
|
109
|
+
};
|
|
92
110
|
Form.TextField = TextField;
|
|
93
111
|
Form.NumberField = NumberField;
|
|
94
112
|
Form.CheckboxField = CheckboxField;
|
|
@@ -98,5 +116,6 @@ export function createForm() {
|
|
|
98
116
|
Form.FileField = FileField;
|
|
99
117
|
Form.ImageField = ImageField;
|
|
100
118
|
Form.SliderField = SliderField;
|
|
119
|
+
Form.RelationField = RelationField;
|
|
101
120
|
return Form;
|
|
102
121
|
}
|
|
@@ -4,7 +4,7 @@ import Pencil from "lucide-solid/icons/pencil";
|
|
|
4
4
|
import ImageIcon from "lucide-solid/icons/image";
|
|
5
5
|
import { Button } from "../Button";
|
|
6
6
|
const image = tv({
|
|
7
|
-
base: "rounded-
|
|
7
|
+
base: "rounded-sm object-cover",
|
|
8
8
|
variants: {
|
|
9
9
|
size: {
|
|
10
10
|
xs: "w-16 h-16",
|
|
@@ -16,7 +16,7 @@ const image = tv({
|
|
|
16
16
|
},
|
|
17
17
|
});
|
|
18
18
|
const placeholder = tv({
|
|
19
|
-
base: "rounded-
|
|
19
|
+
base: "rounded-sm flex items-center justify-center bg-base-200",
|
|
20
20
|
variants: {
|
|
21
21
|
size: {
|
|
22
22
|
xs: "w-16 h-16",
|
|
@@ -70,7 +70,7 @@ export const Image = (props) => {
|
|
|
70
70
|
<img {...imgProps} src={currentSrc()} alt={props.alt} class={image({ size: props.size, class: props.class })}/>
|
|
71
71
|
</Show>
|
|
72
72
|
<Show when={editable}>
|
|
73
|
-
<div class="absolute inset-0 flex items-center justify-center bg-black/10 opacity-0 group-hover:opacity-100 transition-opacity z-10 rounded-
|
|
73
|
+
<div class="absolute inset-0 flex items-center justify-center bg-black/10 opacity-0 group-hover:opacity-100 transition-opacity z-10 rounded-sm">
|
|
74
74
|
<Button size="sm" modifier="square" variant="ghost" onClick={handleEditClick}>
|
|
75
75
|
<Pencil class="w-4 h-4"/>
|
|
76
76
|
</Button>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { JSXElement } from "solid-js";
|
|
2
|
+
export interface RelationPickerProps<T> {
|
|
3
|
+
value: T | T[] | null;
|
|
4
|
+
options: T[];
|
|
5
|
+
onChange: (val: T | T[] | null) => void;
|
|
6
|
+
labelKey: keyof T;
|
|
7
|
+
valueKey: keyof T;
|
|
8
|
+
disabledKey?: keyof T;
|
|
9
|
+
multi?: boolean;
|
|
10
|
+
label?: string;
|
|
11
|
+
variant?: "ghost";
|
|
12
|
+
appearance?: "neutral" | "primary" | "secondary" | "accent" | "info" | "success" | "warning" | "error";
|
|
13
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl";
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
class?: string;
|
|
17
|
+
listboxAction?: JSXElement;
|
|
18
|
+
onTextInputChange?: (text: string) => void;
|
|
19
|
+
defaultFilter?: (option: T[] | Exclude<NonNullable<T>, null>, filter: string) => boolean;
|
|
20
|
+
onLinkClick?: (value: T) => void;
|
|
21
|
+
}
|
|
22
|
+
export declare const RelationPicker: <T>(props: RelationPickerProps<T>) => import("solid-js").JSX.Element;
|
|
23
|
+
export default RelationPicker;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Combobox } from "@kobalte/core/combobox";
|
|
2
|
+
import Check from "lucide-solid/icons/check";
|
|
3
|
+
import Link from "lucide-solid/icons/link";
|
|
4
|
+
import UpDown from "lucide-solid/icons/chevrons-up-down";
|
|
5
|
+
import { For, Show } from "solid-js";
|
|
6
|
+
import { tv } from "tailwind-variants";
|
|
7
|
+
import { Tag } from "./Tag";
|
|
8
|
+
import { Button } from "./Button";
|
|
9
|
+
import { iconSize } from "../constants";
|
|
10
|
+
const input = tv({
|
|
11
|
+
base: "join-item input outline-offset-0",
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
ghost: "input-ghost",
|
|
15
|
+
none: "",
|
|
16
|
+
},
|
|
17
|
+
appearance: {
|
|
18
|
+
neutral: "input-neutral",
|
|
19
|
+
primary: "input-primary",
|
|
20
|
+
secondary: "input-secondary",
|
|
21
|
+
accent: "input-accent",
|
|
22
|
+
info: "input-info",
|
|
23
|
+
success: "input-success",
|
|
24
|
+
warning: "input-warning",
|
|
25
|
+
error: "input-error",
|
|
26
|
+
},
|
|
27
|
+
size: {
|
|
28
|
+
xs: "input-xs",
|
|
29
|
+
sm: "input-sm",
|
|
30
|
+
md: "input-md",
|
|
31
|
+
lg: "input-lg",
|
|
32
|
+
xl: "input-xl",
|
|
33
|
+
},
|
|
34
|
+
tags: {
|
|
35
|
+
true: "h-full py-1.25",
|
|
36
|
+
false: "",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
defaultVariants: {
|
|
40
|
+
size: "sm",
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
const menu = tv({
|
|
44
|
+
base: "menu w-full",
|
|
45
|
+
variants: {
|
|
46
|
+
size: {
|
|
47
|
+
xs: "menu-xs",
|
|
48
|
+
sm: "menu-sm",
|
|
49
|
+
md: "menu-base",
|
|
50
|
+
lg: "menu-lg",
|
|
51
|
+
xl: "menu-xl",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
defaultVariants: {
|
|
55
|
+
size: "sm",
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
export const RelationPicker = (props) => {
|
|
59
|
+
let inputRef;
|
|
60
|
+
const values = () => {
|
|
61
|
+
if (props.multi) {
|
|
62
|
+
return Array.isArray(props.value) ? props.value : props.value ? [props.value] : [];
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return props.value && !Array.isArray(props.value) ? props.value : null;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const options = () => {
|
|
69
|
+
if (props.options.length === 0)
|
|
70
|
+
return [
|
|
71
|
+
{ [props.labelKey]: "No Records Found", [props.valueKey]: "__no_options__", disabled: true },
|
|
72
|
+
];
|
|
73
|
+
return props.options;
|
|
74
|
+
};
|
|
75
|
+
return (<div class="floating-label">
|
|
76
|
+
{props.label && <span>{props.label}</span>}
|
|
77
|
+
<Combobox disabled={props.disabled} multiple={props.multi} value={values()} onChange={props.onChange} options={options()}
|
|
78
|
+
//@ts-ignore, kobalte confusing, just ignore for now...
|
|
79
|
+
optionValue={props.valueKey}
|
|
80
|
+
//@ts-ignore
|
|
81
|
+
optionTextValue={props.labelKey}
|
|
82
|
+
//@ts-ignore
|
|
83
|
+
optionLabel={props.labelKey}
|
|
84
|
+
//@ts-ignore
|
|
85
|
+
optionDisabled={props.disabledKey} placeholder={props.placeholder} onMouseDown={(e) => {
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
inputRef?.focus();
|
|
88
|
+
}} defaultFilter={props.defaultFilter} itemComponent={(itemProps) => (<Combobox.Item item={itemProps.item} class="outline-none focus:bg-base-300 rounded-sm">
|
|
89
|
+
<Combobox.ItemLabel class="flex flex-row justify-between items-center">
|
|
90
|
+
{itemProps.item.textValue}
|
|
91
|
+
<Combobox.ItemIndicator>
|
|
92
|
+
<Check size={16}/>
|
|
93
|
+
</Combobox.ItemIndicator>
|
|
94
|
+
</Combobox.ItemLabel>
|
|
95
|
+
</Combobox.Item>)}>
|
|
96
|
+
<Combobox.Control class="join w-full max-w-[20rem]">
|
|
97
|
+
{(state) => (<>
|
|
98
|
+
<div class={input({
|
|
99
|
+
variant: props.variant,
|
|
100
|
+
appearance: props.appearance,
|
|
101
|
+
size: props.size,
|
|
102
|
+
class: props.class,
|
|
103
|
+
tags: props.multi && Array.isArray(props.value) && props.value.length > 0,
|
|
104
|
+
})}>
|
|
105
|
+
<Show when={props.multi} fallback={<>
|
|
106
|
+
{!props.multi && values() && (<Button variant="ghost" appearance="primary" size="xs" modifier="square" onClick={() => props.onLinkClick?.(props.value)}>
|
|
107
|
+
<Link class="w-[1em] h-[1em]"/>
|
|
108
|
+
</Button>)}
|
|
109
|
+
<Combobox.Input onBlur={(e) => {
|
|
110
|
+
if (!props.value) {
|
|
111
|
+
e.currentTarget.value = "";
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
e.currentTarget.value = String(state.selectedOptions()[0][props.labelKey]);
|
|
115
|
+
}
|
|
116
|
+
}} ref={inputRef} onInput={(e) => props.onTextInputChange?.(e.currentTarget.value)}/>
|
|
117
|
+
</>}>
|
|
118
|
+
<div class="flex flex-wrap gap-1 w-full">
|
|
119
|
+
<For each={state.selectedOptions()}>
|
|
120
|
+
{(option) => (<span onPointerDown={(e) => e.stopPropagation()}>
|
|
121
|
+
<Tag appearance="neutral" variant="soft" title={String(option[props.labelKey])} onDelete={() => state.remove(option)}/>
|
|
122
|
+
</span>)}
|
|
123
|
+
</For>
|
|
124
|
+
<Combobox.Input class="w-[unset]" onBlur={(e) => (e.currentTarget.value = "")} ref={inputRef} onInput={(e) => props.onTextInputChange?.(e.currentTarget.value)}/>
|
|
125
|
+
</div>
|
|
126
|
+
</Show>
|
|
127
|
+
</div>
|
|
128
|
+
<Combobox.Trigger as={Button} size={props.size} modifier="square" class="join-item">
|
|
129
|
+
<Combobox.Icon>
|
|
130
|
+
<UpDown size={iconSize[props.size ?? "sm"]}/>
|
|
131
|
+
</Combobox.Icon>
|
|
132
|
+
</Combobox.Trigger>
|
|
133
|
+
</>)}
|
|
134
|
+
</Combobox.Control>
|
|
135
|
+
<Combobox.Portal>
|
|
136
|
+
<Combobox.Content class="rounded-box bg-base-100 shadow-md border border-base-200 z-20 max-h-100 overflow-auto">
|
|
137
|
+
<Combobox.Listbox class={menu({ size: props.size })}/>
|
|
138
|
+
{props.listboxAction}
|
|
139
|
+
</Combobox.Content>
|
|
140
|
+
</Combobox.Portal>
|
|
141
|
+
</Combobox>
|
|
142
|
+
</div>);
|
|
143
|
+
};
|
|
144
|
+
export default RelationPicker;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Select as KSelect } from "@kobalte/core/select";
|
|
2
2
|
import Check from "lucide-solid/icons/check";
|
|
3
|
-
import
|
|
3
|
+
import UpDown from "lucide-solid/icons/chevrons-up-down";
|
|
4
4
|
import { tv } from "tailwind-variants";
|
|
5
|
+
import { Button } from "../Button";
|
|
6
|
+
import { iconSize } from "../../constants";
|
|
5
7
|
const trigger = tv({
|
|
6
|
-
base: "input outline-offset-0 flex justify-between items-center",
|
|
8
|
+
base: "input outline-offset-0 flex justify-between items-center join-item",
|
|
7
9
|
variants: {
|
|
8
10
|
variant: {
|
|
9
11
|
ghost: "input-ghost",
|
|
@@ -59,21 +61,23 @@ export const Select = (props) => {
|
|
|
59
61
|
</KSelect.ItemLabel>
|
|
60
62
|
</KSelect.Item>);
|
|
61
63
|
}}>
|
|
62
|
-
<KSelect.Trigger class=
|
|
64
|
+
<KSelect.Trigger class="join w-full max-w-[20rem]">
|
|
65
|
+
<div class={trigger({
|
|
63
66
|
variant: props.variant,
|
|
64
67
|
appearance: props.appearance,
|
|
65
68
|
size: props.size,
|
|
66
69
|
class: props.class,
|
|
67
70
|
})}>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
<KSelect.Value>
|
|
72
|
+
{(state) => String(props.labelKey ? state.selectedOption()?.[props.labelKey] : "")}
|
|
73
|
+
</KSelect.Value>
|
|
74
|
+
</div>
|
|
75
|
+
<KSelect.Icon as={Button} class="join-item" modifier="square" size={props.size}>
|
|
76
|
+
<UpDown size={iconSize[props.size ?? "sm"]}/>
|
|
73
77
|
</KSelect.Icon>
|
|
74
78
|
</KSelect.Trigger>
|
|
75
79
|
<KSelect.Portal>
|
|
76
|
-
<KSelect.Content class="rounded-box bg-base-100 shadow-md border border-base-200 z-20">
|
|
80
|
+
<KSelect.Content class="rounded-box bg-base-100 shadow-md border border-base-200 z-20 max-h-100 overflow-auto">
|
|
77
81
|
<KSelect.Listbox class={menu({ size: props.size })}/>
|
|
78
82
|
</KSelect.Content>
|
|
79
83
|
</KSelect.Portal>
|
|
@@ -164,7 +164,7 @@ export const Table = (props) => {
|
|
|
164
164
|
<Loader class="w-9 h-9 animate-spin"/>
|
|
165
165
|
</div>)}>
|
|
166
166
|
<Show when={rowCount() > 0} fallback={props.emptyState || <div class="text-center py-4">No results found.</div>}>
|
|
167
|
-
<table class={tableClass({ class: props.class })}>
|
|
167
|
+
<table class={tableClass({ class: props.class, size: props.size })}>
|
|
168
168
|
<Show when={props.headers}>
|
|
169
169
|
<thead>
|
|
170
170
|
<For each={table.getHeaderGroups()}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { For } from "solid-js";
|
|
2
2
|
import Monitor from "lucide-solid/icons/monitor";
|
|
3
3
|
import { tv } from "tailwind-variants";
|
|
4
4
|
import { DropdownMenu } from "../DropdownMenu";
|
|
@@ -11,9 +11,8 @@ const SystemOption = () => (<span class="flex items-center gap-1">
|
|
|
11
11
|
</span>);
|
|
12
12
|
export const ThemeSwitch = (props) => {
|
|
13
13
|
const options = () => props.options;
|
|
14
|
-
const
|
|
14
|
+
const theme = localStorage.getItem("theme");
|
|
15
15
|
const handleChange = (val) => {
|
|
16
|
-
setTheme(val);
|
|
17
16
|
if (val === "system") {
|
|
18
17
|
localStorage.removeItem(THEME_KEY);
|
|
19
18
|
document.documentElement.removeAttribute("data-theme");
|
|
@@ -23,12 +22,11 @@ export const ThemeSwitch = (props) => {
|
|
|
23
22
|
document.documentElement.setAttribute("data-theme", val);
|
|
24
23
|
};
|
|
25
24
|
const getCurrentLabel = () => {
|
|
26
|
-
|
|
27
|
-
if (current === "system") {
|
|
25
|
+
if (theme === "system") {
|
|
28
26
|
return <SystemOption />;
|
|
29
27
|
}
|
|
30
|
-
const option = options().find((opt) => opt.value ===
|
|
31
|
-
return option?.label ||
|
|
28
|
+
const option = options().find((opt) => opt.value === theme);
|
|
29
|
+
return option?.label || theme;
|
|
32
30
|
};
|
|
33
31
|
return (<DropdownMenu>
|
|
34
32
|
<DropdownMenu.Trigger class={trigger({ class: props.triggerClass })}>
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./Form";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./Form";
|
|
File without changes
|
|
File without changes
|