@unofficialbox/box-open-elements-solid 0.0.0-stage → 0.42.2
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 +60 -2
- package/dist/button.d.ts +21 -0
- package/dist/button.js +22 -0
- package/dist/combobox.d.ts +42 -0
- package/dist/combobox.js +35 -0
- package/dist/create-web-component.d.ts +15 -0
- package/dist/create-web-component.js +35 -0
- package/dist/dialog.d.ts +42 -0
- package/dist/dialog.js +37 -0
- package/dist/drawer.d.ts +39 -0
- package/dist/drawer.js +23 -0
- package/dist/events.d.ts +9 -0
- package/dist/events.js +1 -0
- package/dist/explorer-selection.d.ts +6 -0
- package/dist/explorer-selection.js +12 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +8 -0
- package/dist/select.d.ts +35 -0
- package/dist/select.js +42 -0
- package/dist/text-field.d.ts +41 -0
- package/dist/text-field.js +54 -0
- package/package.json +51 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kyle @ Unofficial Box
|
|
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
CHANGED
|
@@ -1,3 +1,61 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SolidJS adapter
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@unofficialbox/box-open-elements-solid` is implemented, awaiting independent review,
|
|
4
|
+
and **not published**. Use the workspace or a locally packed tarball for now.
|
|
5
|
+
The package version follows core lockstep; it does not indicate npm availability.
|
|
6
|
+
|
|
7
|
+
Exports: `Button`, `TextField`, `Select`, `Dialog`, `Combobox`, `Drawer`, `createWebComponent`,
|
|
8
|
+
`ExplorerSelectionController`, and `useExplorerSelectionController`, with public
|
|
9
|
+
prop/event/ref declarations and per-component subpath exports.
|
|
10
|
+
|
|
11
|
+
Peers: core `^0.42.2` and solid-js `^1.9.17`.
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { TextField, Select, Dialog } from "@unofficialbox/box-open-elements-solid";
|
|
15
|
+
|
|
16
|
+
// Render inside your framework component. Pass normal JSX props, including
|
|
17
|
+
// reactive signal reads in Solid. Structured values go through BOE setters.
|
|
18
|
+
<TextField name="title" label="Title" value="Example"
|
|
19
|
+
ref={element => element?.focus()}
|
|
20
|
+
onValueChanged={event => console.log(event.detail.value)} />;
|
|
21
|
+
<Select options={[{ label: "One", value: "1" }]} value="1" />;
|
|
22
|
+
<Dialog open={false} heading="Details"><span slot="footer">Footer</span></Dialog>;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Solid props remain getter-backed through `splitProps`; the host does not remount
|
|
26
|
+
when signals update. Call `useExplorerSelectionController` within a Solid owner;
|
|
27
|
+
it returns an accessor and owner disposal releases the subscription. Refs follow
|
|
28
|
+
Solid's element callback/JSX assignment contract; callbacks are not called with
|
|
29
|
+
null at disposal. Use `onCleanup` for external ref-owned resources.
|
|
30
|
+
|
|
31
|
+
Mapped BOE event callbacks receive the actual DOM event; `preventDefault` and
|
|
32
|
+
`stopPropagation` act on it. Cancellation works when the underlying event is
|
|
33
|
+
cancelable; BOE Dialog's `cancel` notification itself is not cancelable. Factory
|
|
34
|
+
`events` maps preserve exact spelling/case, and listeners are removed when the
|
|
35
|
+
framework owner unmounts. Temporary DOM disconnect/reconnect retains the owner.
|
|
36
|
+
The wrappers retain BOE's optional-property semantics: omitted scalar props leave
|
|
37
|
+
the element value alone; disabled/invalid default to false. Use explicit false,
|
|
38
|
+
empty string, or empty array to clear controlled values. BOE Select intentionally
|
|
39
|
+
reflects its assigned options array as JSON. Host attributes, children, and slots
|
|
40
|
+
remain framework-native; use Solid's `attr:*`/`bool:*` for explicit attribute mode.
|
|
41
|
+
|
|
42
|
+
SSR imports require no DOM globals. Server rendering emits inert custom-element
|
|
43
|
+
hosts and light-DOM children; controlled properties and arrays are assigned on
|
|
44
|
+
client hydration, so do not expect populated shadow DOM before JavaScript runs.
|
|
45
|
+
Mapped listeners attach before initial property sync, including synchronous
|
|
46
|
+
`open-changed` notifications from initially-open Dialog and Drawer. Browser
|
|
47
|
+
fixtures cover closed-first and initially-open client/hydrated rendering.
|
|
48
|
+
Include `generateHydrationScript()` in the server HTML and compile both halves
|
|
49
|
+
with Solid's hydratable JSX compiler. SolidStart is not verified.
|
|
50
|
+
|
|
51
|
+
Validation: `bun run frameworks:solid`, `bun run frameworks:solid:ssr`,
|
|
52
|
+
`bun run test -- packages/solid`, `bun run frameworks:jsx:browser`, and
|
|
53
|
+
`bun run adapters:pack-check`. See [support status](../../docs/integration/framework-adapters.md)
|
|
54
|
+
and [release requirements](../../RELEASING.md).
|
|
55
|
+
|
|
56
|
+
Design references: [Solid dynamic hosts](https://docs.solidjs.com/reference/components/dynamic),
|
|
57
|
+
[exact native events](https://docs.solidjs.com/reference/jsx-attributes/on), and
|
|
58
|
+
[owner cleanup](https://docs.solidjs.com/reference/lifecycle/on-cleanup).
|
|
59
|
+
The installed 1.9.17 `solid-js/web` source confirms dynamic host hydration-key
|
|
60
|
+
reuse and separate server rendering. The factory uses those runtime APIs so the
|
|
61
|
+
published adapter itself needs no JSX compiler transform.
|
package/dist/button.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Button as ButtonElement } from "@unofficialbox/box-open-elements/button";
|
|
2
|
+
import { type WebComponentProps } from "./create-web-component.js";
|
|
3
|
+
import type { NativeEventHandler } from "./events.js";
|
|
4
|
+
export type ButtonProps = Omit<WebComponentProps, "onClick"> & {
|
|
5
|
+
label?: string;
|
|
6
|
+
accessibleLabel?: string;
|
|
7
|
+
tone?: string;
|
|
8
|
+
size?: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
onClick?: NativeEventHandler<ButtonElement, MouseEvent>;
|
|
11
|
+
};
|
|
12
|
+
export declare const Button: import("solid-js").Component<Omit<WebComponentProps, "onClick"> & {
|
|
13
|
+
label?: string;
|
|
14
|
+
accessibleLabel?: string;
|
|
15
|
+
tone?: string;
|
|
16
|
+
size?: string;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
onClick?: NativeEventHandler<ButtonElement, MouseEvent>;
|
|
19
|
+
} & {
|
|
20
|
+
ref?: ButtonElement | ((element: ButtonElement) => void) | undefined;
|
|
21
|
+
}>;
|
package/dist/button.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Button as ButtonElement } from "@unofficialbox/box-open-elements/button";
|
|
2
|
+
import { createWebComponent } from "./create-web-component.js";
|
|
3
|
+
ButtonElement.register();
|
|
4
|
+
export const Button = createWebComponent({
|
|
5
|
+
tagName: "box-button",
|
|
6
|
+
propertyNames: ["label", "accessibleLabel", "tone", "size", "disabled"],
|
|
7
|
+
events: [{ propName: "onClick", eventName: "click" }],
|
|
8
|
+
sync: (element, props) => {
|
|
9
|
+
if (props.label !== undefined) {
|
|
10
|
+
element.label = props.label;
|
|
11
|
+
}
|
|
12
|
+
if (props.accessibleLabel !== undefined)
|
|
13
|
+
element.accessibleLabel = props.accessibleLabel;
|
|
14
|
+
if (props.tone !== undefined) {
|
|
15
|
+
element.tone = props.tone;
|
|
16
|
+
}
|
|
17
|
+
if (props.size !== undefined) {
|
|
18
|
+
element.size = props.size;
|
|
19
|
+
}
|
|
20
|
+
element.disabled = Boolean(props.disabled);
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Combobox as ComboboxElement } from "@unofficialbox/box-open-elements/combobox";
|
|
2
|
+
import { type WebComponentProps } from "./create-web-component.js";
|
|
3
|
+
import type { CustomEventHandler, ValueChangedDetail } from "./events.js";
|
|
4
|
+
export type ComboboxOption = {
|
|
5
|
+
label: string;
|
|
6
|
+
value: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
group?: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type ComboboxProps = WebComponentProps & {
|
|
12
|
+
label?: string;
|
|
13
|
+
value?: string;
|
|
14
|
+
options?: ComboboxOption[];
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
placement?: string;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
name?: string;
|
|
19
|
+
invalid?: boolean;
|
|
20
|
+
errorMessage?: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
required?: boolean;
|
|
23
|
+
hideLabel?: boolean;
|
|
24
|
+
onValueChanged?: CustomEventHandler<ComboboxElement, ValueChangedDetail>;
|
|
25
|
+
};
|
|
26
|
+
export declare const Combobox: import("solid-js").Component<WebComponentProps & {
|
|
27
|
+
label?: string;
|
|
28
|
+
value?: string;
|
|
29
|
+
options?: ComboboxOption[];
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
placement?: string;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
name?: string;
|
|
34
|
+
invalid?: boolean;
|
|
35
|
+
errorMessage?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
required?: boolean;
|
|
38
|
+
hideLabel?: boolean;
|
|
39
|
+
onValueChanged?: CustomEventHandler<ComboboxElement, ValueChangedDetail>;
|
|
40
|
+
} & {
|
|
41
|
+
ref?: ComboboxElement | ((element: ComboboxElement) => void) | undefined;
|
|
42
|
+
}>;
|
package/dist/combobox.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Combobox as ComboboxElement } from "@unofficialbox/box-open-elements/combobox";
|
|
2
|
+
import { createWebComponent } from "./create-web-component.js";
|
|
3
|
+
ComboboxElement.register();
|
|
4
|
+
export const Combobox = createWebComponent({
|
|
5
|
+
tagName: "box-combobox",
|
|
6
|
+
propertyNames: [
|
|
7
|
+
"label", "value", "options", "placeholder", "placement", "disabled",
|
|
8
|
+
"name", "invalid", "errorMessage", "description", "required", "hideLabel",
|
|
9
|
+
],
|
|
10
|
+
events: [{ propName: "onValueChanged", eventName: "value-changed" }],
|
|
11
|
+
sync: (element, props) => {
|
|
12
|
+
if (props.label !== undefined)
|
|
13
|
+
element.label = props.label;
|
|
14
|
+
if (props.value !== undefined)
|
|
15
|
+
element.value = props.value;
|
|
16
|
+
if (props.options !== undefined)
|
|
17
|
+
element.options = props.options;
|
|
18
|
+
if (props.placeholder !== undefined)
|
|
19
|
+
element.placeholder = props.placeholder;
|
|
20
|
+
if (props.placement !== undefined)
|
|
21
|
+
element.placement = props.placement;
|
|
22
|
+
if (props.name !== undefined)
|
|
23
|
+
element.name = props.name;
|
|
24
|
+
if (props.errorMessage !== undefined)
|
|
25
|
+
element.errorMessage = props.errorMessage;
|
|
26
|
+
if (props.description !== undefined)
|
|
27
|
+
element.description = props.description;
|
|
28
|
+
if (props.required !== undefined)
|
|
29
|
+
element.required = props.required;
|
|
30
|
+
if (props.hideLabel !== undefined)
|
|
31
|
+
element.hideLabel = props.hideLabel;
|
|
32
|
+
element.disabled = Boolean(props.disabled);
|
|
33
|
+
element.invalid = Boolean(props.invalid);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Component, type JSX } from "solid-js";
|
|
2
|
+
export type WebComponentProps = Omit<JSX.HTMLAttributes<HTMLElement>, "ref" | "onCancel">;
|
|
3
|
+
export type CreateWebComponentOptions<E extends HTMLElement, P> = {
|
|
4
|
+
tagName: string;
|
|
5
|
+
sync: (element: E, props: P) => void;
|
|
6
|
+
propertyNames?: ReadonlyArray<keyof P & string>;
|
|
7
|
+
events?: ReadonlyArray<{
|
|
8
|
+
propName: keyof P & string;
|
|
9
|
+
eventName: string;
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
/** A stable host with reactive property synchronization and owner-scoped listeners. */
|
|
13
|
+
export declare function createWebComponent<E extends HTMLElement, P extends object>(options: CreateWebComponentOptions<E, P>): Component<P & {
|
|
14
|
+
ref?: E | ((element: E) => void);
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createRenderEffect, mergeProps, onCleanup, splitProps, untrack } from "solid-js";
|
|
2
|
+
import { createDynamic } from "solid-js/web";
|
|
3
|
+
/** A stable host with reactive property synchronization and owner-scoped listeners. */
|
|
4
|
+
export function createWebComponent(options) {
|
|
5
|
+
return props => {
|
|
6
|
+
// splitProps preserves Solid's getter-backed props; spreading here would
|
|
7
|
+
// freeze signal values at component creation.
|
|
8
|
+
const [, host] = splitProps(props, [
|
|
9
|
+
...(options.propertyNames ?? []),
|
|
10
|
+
...(options.events ?? []).map(binding => binding.propName),
|
|
11
|
+
"ref",
|
|
12
|
+
]);
|
|
13
|
+
return createDynamic(() => options.tagName, mergeProps(host, {
|
|
14
|
+
ref(element) {
|
|
15
|
+
const subscriptions = (options.events ?? []).map(binding => {
|
|
16
|
+
const listener = (event) => {
|
|
17
|
+
const handler = props[binding.propName];
|
|
18
|
+
if (typeof handler === "function")
|
|
19
|
+
untrack(() => handler(event));
|
|
20
|
+
};
|
|
21
|
+
element.addEventListener(binding.eventName, listener);
|
|
22
|
+
return { ...binding, listener };
|
|
23
|
+
});
|
|
24
|
+
onCleanup(() => {
|
|
25
|
+
for (const binding of subscriptions)
|
|
26
|
+
element.removeEventListener(binding.eventName, binding.listener);
|
|
27
|
+
});
|
|
28
|
+
createRenderEffect(() => options.sync(element, props));
|
|
29
|
+
const ref = props.ref;
|
|
30
|
+
if (typeof ref === "function")
|
|
31
|
+
ref(element);
|
|
32
|
+
},
|
|
33
|
+
}));
|
|
34
|
+
};
|
|
35
|
+
}
|
package/dist/dialog.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import { Dialog as DialogElement } from "@unofficialbox/box-open-elements/dialog";
|
|
3
|
+
import { type WebComponentProps } from "./create-web-component.js";
|
|
4
|
+
import type { CustomEventHandler } from "./events.js";
|
|
5
|
+
export type DialogConfirmTone = "primary" | "danger";
|
|
6
|
+
export type DialogSize = "small" | "medium" | "large" | "fullscreen";
|
|
7
|
+
export type DialogProps = WebComponentProps & {
|
|
8
|
+
children?: JSX.Element;
|
|
9
|
+
open?: boolean;
|
|
10
|
+
heading?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
confirmLabel?: string;
|
|
13
|
+
confirmTone?: DialogConfirmTone;
|
|
14
|
+
confirmDisabled?: boolean;
|
|
15
|
+
confirmBusy?: boolean;
|
|
16
|
+
confirmBusyLabel?: string;
|
|
17
|
+
size?: DialogSize;
|
|
18
|
+
onOpenChanged?: CustomEventHandler<DialogElement, {
|
|
19
|
+
open: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
onConfirm?: CustomEventHandler<DialogElement, null>;
|
|
22
|
+
onCancel?: CustomEventHandler<DialogElement, null>;
|
|
23
|
+
};
|
|
24
|
+
export declare const Dialog: import("solid-js").Component<WebComponentProps & {
|
|
25
|
+
children?: JSX.Element;
|
|
26
|
+
open?: boolean;
|
|
27
|
+
heading?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
confirmLabel?: string;
|
|
30
|
+
confirmTone?: DialogConfirmTone;
|
|
31
|
+
confirmDisabled?: boolean;
|
|
32
|
+
confirmBusy?: boolean;
|
|
33
|
+
confirmBusyLabel?: string;
|
|
34
|
+
size?: DialogSize;
|
|
35
|
+
onOpenChanged?: CustomEventHandler<DialogElement, {
|
|
36
|
+
open: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
onConfirm?: CustomEventHandler<DialogElement, null>;
|
|
39
|
+
onCancel?: CustomEventHandler<DialogElement, null>;
|
|
40
|
+
} & {
|
|
41
|
+
ref?: DialogElement | ((element: DialogElement) => void) | undefined;
|
|
42
|
+
}>;
|
package/dist/dialog.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Dialog as DialogElement } from "@unofficialbox/box-open-elements/dialog";
|
|
2
|
+
import { createWebComponent } from "./create-web-component.js";
|
|
3
|
+
DialogElement.register();
|
|
4
|
+
export const Dialog = createWebComponent({
|
|
5
|
+
tagName: "box-dialog",
|
|
6
|
+
propertyNames: ["open", "heading", "description", "confirmLabel", "confirmTone", "confirmDisabled", "confirmBusy", "confirmBusyLabel", "size"],
|
|
7
|
+
events: [
|
|
8
|
+
{ propName: "onOpenChanged", eventName: "open-changed" },
|
|
9
|
+
{ propName: "onConfirm", eventName: "confirm" },
|
|
10
|
+
{ propName: "onCancel", eventName: "cancel" },
|
|
11
|
+
],
|
|
12
|
+
sync: (element, props) => {
|
|
13
|
+
if (props.heading !== undefined) {
|
|
14
|
+
element.heading = props.heading;
|
|
15
|
+
}
|
|
16
|
+
if (props.description !== undefined) {
|
|
17
|
+
element.description = props.description;
|
|
18
|
+
}
|
|
19
|
+
if (props.confirmLabel !== undefined) {
|
|
20
|
+
element.confirmLabel = props.confirmLabel;
|
|
21
|
+
}
|
|
22
|
+
if (props.confirmTone !== undefined)
|
|
23
|
+
element.confirmTone = props.confirmTone;
|
|
24
|
+
if (props.confirmDisabled !== undefined)
|
|
25
|
+
element.confirmDisabled = props.confirmDisabled;
|
|
26
|
+
if (props.confirmBusy !== undefined)
|
|
27
|
+
element.confirmBusy = props.confirmBusy;
|
|
28
|
+
if (props.confirmBusyLabel !== undefined)
|
|
29
|
+
element.confirmBusyLabel = props.confirmBusyLabel;
|
|
30
|
+
if (props.size !== undefined) {
|
|
31
|
+
element.size = props.size;
|
|
32
|
+
}
|
|
33
|
+
if (props.open !== undefined) {
|
|
34
|
+
element.open = props.open;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
});
|
package/dist/drawer.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import { Drawer as DrawerRef } from "@unofficialbox/box-open-elements/drawer";
|
|
3
|
+
import { type WebComponentProps } from "./create-web-component.js";
|
|
4
|
+
import type { CustomEventHandler } from "./events.js";
|
|
5
|
+
export type { DrawerRef };
|
|
6
|
+
export type DrawerProps = WebComponentProps & {
|
|
7
|
+
children?: JSX.Element;
|
|
8
|
+
heading?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
open?: boolean;
|
|
11
|
+
position?: string;
|
|
12
|
+
size?: string;
|
|
13
|
+
busy?: boolean;
|
|
14
|
+
hideCloseButton?: boolean;
|
|
15
|
+
onOpenChanged?: CustomEventHandler<DrawerRef, {
|
|
16
|
+
open: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
onDismiss?: CustomEventHandler<DrawerRef, {
|
|
19
|
+
source: "close-button" | "backdrop" | "escape";
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
22
|
+
export declare const Drawer: import("solid-js").Component<WebComponentProps & {
|
|
23
|
+
children?: JSX.Element;
|
|
24
|
+
heading?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
open?: boolean;
|
|
27
|
+
position?: string;
|
|
28
|
+
size?: string;
|
|
29
|
+
busy?: boolean;
|
|
30
|
+
hideCloseButton?: boolean;
|
|
31
|
+
onOpenChanged?: CustomEventHandler<DrawerRef, {
|
|
32
|
+
open: boolean;
|
|
33
|
+
}>;
|
|
34
|
+
onDismiss?: CustomEventHandler<DrawerRef, {
|
|
35
|
+
source: "close-button" | "backdrop" | "escape";
|
|
36
|
+
}>;
|
|
37
|
+
} & {
|
|
38
|
+
ref?: DrawerRef | ((element: DrawerRef) => void) | undefined;
|
|
39
|
+
}>;
|
package/dist/drawer.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Drawer as DrawerRef } from "@unofficialbox/box-open-elements/drawer";
|
|
2
|
+
import { createWebComponent } from "./create-web-component.js";
|
|
3
|
+
export const Drawer = createWebComponent({
|
|
4
|
+
tagName: DrawerRef.tagName,
|
|
5
|
+
propertyNames: ["heading", "description", "open", "position", "size", "busy", "hideCloseButton"],
|
|
6
|
+
events: [{ propName: "onOpenChanged", eventName: "open-changed" }, { propName: "onDismiss", eventName: "dismiss" }],
|
|
7
|
+
sync: (element, props) => {
|
|
8
|
+
if (props.heading !== undefined)
|
|
9
|
+
element.heading = props.heading;
|
|
10
|
+
if (props.description !== undefined)
|
|
11
|
+
element.description = props.description;
|
|
12
|
+
if (props.open !== undefined)
|
|
13
|
+
element.open = props.open;
|
|
14
|
+
if (props.position !== undefined)
|
|
15
|
+
element.position = props.position;
|
|
16
|
+
if (props.size !== undefined)
|
|
17
|
+
element.size = props.size;
|
|
18
|
+
if (props.busy !== undefined)
|
|
19
|
+
element.busy = props.busy;
|
|
20
|
+
if (props.hideCloseButton !== undefined)
|
|
21
|
+
element.hideCloseButton = props.hideCloseButton;
|
|
22
|
+
},
|
|
23
|
+
});
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type CustomEventHandler<E extends HTMLElement, Detail> = (event: CustomEvent<Detail> & {
|
|
2
|
+
currentTarget: E;
|
|
3
|
+
}) => void;
|
|
4
|
+
export type NativeEventHandler<E extends HTMLElement, Ev extends Event = Event> = (event: Ev & {
|
|
5
|
+
currentTarget: E;
|
|
6
|
+
}) => void;
|
|
7
|
+
export type ValueChangedDetail = {
|
|
8
|
+
value: string;
|
|
9
|
+
};
|
package/dist/events.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Accessor } from "solid-js";
|
|
2
|
+
import { ExplorerSelectionController, type ExplorerSelectionState } from "@unofficialbox/box-open-elements/patterns/content-explorer/selection";
|
|
3
|
+
export { ExplorerSelectionController };
|
|
4
|
+
export type { ExplorerSelectionState };
|
|
5
|
+
/** Call inside a Solid owner; disposal releases the controller subscription. */
|
|
6
|
+
export declare function useExplorerSelectionController(controller: ExplorerSelectionController): Accessor<Readonly<ExplorerSelectionState>>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createSignal, getOwner, onCleanup } from "solid-js";
|
|
2
|
+
import { ExplorerSelectionController } from "@unofficialbox/box-open-elements/patterns/content-explorer/selection";
|
|
3
|
+
export { ExplorerSelectionController };
|
|
4
|
+
/** Call inside a Solid owner; disposal releases the controller subscription. */
|
|
5
|
+
export function useExplorerSelectionController(controller) {
|
|
6
|
+
if (!getOwner())
|
|
7
|
+
throw new Error("useExplorerSelectionController requires a Solid reactive owner.");
|
|
8
|
+
const [state, setState] = createSignal(controller.getState());
|
|
9
|
+
const unsubscribe = controller.subscribe("selectionChanged", () => setState(controller.getState()));
|
|
10
|
+
onCleanup(unsubscribe);
|
|
11
|
+
return state;
|
|
12
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createWebComponent, type WebComponentProps, type CreateWebComponentOptions } from "./create-web-component.js";
|
|
2
|
+
export type { CustomEventHandler, NativeEventHandler, ValueChangedDetail } from "./events.js";
|
|
3
|
+
export { Button, type ButtonProps } from "./button.js";
|
|
4
|
+
export { TextField, type TextFieldProps } from "./text-field.js";
|
|
5
|
+
export { Select, type SelectProps, type SelectOption } from "./select.js";
|
|
6
|
+
export { Dialog, type DialogProps, type DialogConfirmTone, type DialogSize } from "./dialog.js";
|
|
7
|
+
export { ExplorerSelectionController, useExplorerSelectionController, type ExplorerSelectionState } from "./explorer-selection.js";
|
|
8
|
+
export { Combobox, type ComboboxProps, type ComboboxOption } from "./combobox.js";
|
|
9
|
+
export { Drawer, type DrawerProps, type DrawerRef } from "./drawer.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createWebComponent } from "./create-web-component.js";
|
|
2
|
+
export { Button } from "./button.js";
|
|
3
|
+
export { TextField } from "./text-field.js";
|
|
4
|
+
export { Select } from "./select.js";
|
|
5
|
+
export { Dialog } from "./dialog.js";
|
|
6
|
+
export { ExplorerSelectionController, useExplorerSelectionController } from "./explorer-selection.js";
|
|
7
|
+
export { Combobox } from "./combobox.js";
|
|
8
|
+
export { Drawer } from "./drawer.js";
|
package/dist/select.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Select as SelectElement } from "@unofficialbox/box-open-elements/select";
|
|
2
|
+
import { type WebComponentProps } from "./create-web-component.js";
|
|
3
|
+
import type { CustomEventHandler, ValueChangedDetail } from "./events.js";
|
|
4
|
+
export type SelectOption = {
|
|
5
|
+
label: string;
|
|
6
|
+
value: string;
|
|
7
|
+
};
|
|
8
|
+
export type SelectProps = WebComponentProps & {
|
|
9
|
+
label?: string;
|
|
10
|
+
value?: string;
|
|
11
|
+
options?: SelectOption[];
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
name?: string;
|
|
14
|
+
invalid?: boolean;
|
|
15
|
+
errorMessage?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
hideLabel?: boolean;
|
|
19
|
+
onValueChanged?: CustomEventHandler<SelectElement, ValueChangedDetail>;
|
|
20
|
+
};
|
|
21
|
+
export declare const Select: import("solid-js").Component<WebComponentProps & {
|
|
22
|
+
label?: string;
|
|
23
|
+
value?: string;
|
|
24
|
+
options?: SelectOption[];
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
name?: string;
|
|
27
|
+
invalid?: boolean;
|
|
28
|
+
errorMessage?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
required?: boolean;
|
|
31
|
+
hideLabel?: boolean;
|
|
32
|
+
onValueChanged?: CustomEventHandler<SelectElement, ValueChangedDetail>;
|
|
33
|
+
} & {
|
|
34
|
+
ref?: SelectElement | ((element: SelectElement) => void) | undefined;
|
|
35
|
+
}>;
|
package/dist/select.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Select as SelectElement } from "@unofficialbox/box-open-elements/select";
|
|
2
|
+
import { createWebComponent } from "./create-web-component.js";
|
|
3
|
+
SelectElement.register();
|
|
4
|
+
export const Select = createWebComponent({
|
|
5
|
+
tagName: "box-select",
|
|
6
|
+
propertyNames: [
|
|
7
|
+
"label",
|
|
8
|
+
"value",
|
|
9
|
+
"options",
|
|
10
|
+
"disabled",
|
|
11
|
+
"name",
|
|
12
|
+
"invalid",
|
|
13
|
+
"errorMessage",
|
|
14
|
+
"description", "required", "hideLabel",
|
|
15
|
+
],
|
|
16
|
+
events: [{ propName: "onValueChanged", eventName: "value-changed" }],
|
|
17
|
+
sync: (element, props) => {
|
|
18
|
+
if (props.description !== undefined)
|
|
19
|
+
element.description = props.description;
|
|
20
|
+
if (props.required !== undefined)
|
|
21
|
+
element.required = props.required;
|
|
22
|
+
if (props.hideLabel !== undefined)
|
|
23
|
+
element.hideLabel = props.hideLabel;
|
|
24
|
+
if (props.label !== undefined) {
|
|
25
|
+
element.label = props.label;
|
|
26
|
+
}
|
|
27
|
+
if (props.value !== undefined) {
|
|
28
|
+
element.value = props.value;
|
|
29
|
+
}
|
|
30
|
+
if (props.options !== undefined) {
|
|
31
|
+
element.options = props.options;
|
|
32
|
+
}
|
|
33
|
+
if (props.name !== undefined) {
|
|
34
|
+
element.name = props.name;
|
|
35
|
+
}
|
|
36
|
+
if (props.errorMessage !== undefined) {
|
|
37
|
+
element.errorMessage = props.errorMessage;
|
|
38
|
+
}
|
|
39
|
+
element.disabled = Boolean(props.disabled);
|
|
40
|
+
element.invalid = Boolean(props.invalid);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { TextField as TextFieldElement } from "@unofficialbox/box-open-elements/text-field";
|
|
2
|
+
import { type WebComponentProps } from "./create-web-component.js";
|
|
3
|
+
import type { CustomEventHandler, ValueChangedDetail } from "./events.js";
|
|
4
|
+
export type TextFieldProps = WebComponentProps & {
|
|
5
|
+
label?: string;
|
|
6
|
+
value?: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
type?: "text" | "password" | "email" | "tel" | "url" | "search" | "number";
|
|
9
|
+
reveal?: boolean;
|
|
10
|
+
revealLabel?: string;
|
|
11
|
+
autocomplete?: string;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
readonly?: boolean;
|
|
14
|
+
name?: string;
|
|
15
|
+
invalid?: boolean;
|
|
16
|
+
errorMessage?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
required?: boolean;
|
|
19
|
+
hideLabel?: boolean;
|
|
20
|
+
onValueChanged?: CustomEventHandler<TextFieldElement, ValueChangedDetail>;
|
|
21
|
+
};
|
|
22
|
+
export declare const TextField: import("solid-js").Component<WebComponentProps & {
|
|
23
|
+
label?: string;
|
|
24
|
+
value?: string;
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
type?: "text" | "password" | "email" | "tel" | "url" | "search" | "number";
|
|
27
|
+
reveal?: boolean;
|
|
28
|
+
revealLabel?: string;
|
|
29
|
+
autocomplete?: string;
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
readonly?: boolean;
|
|
32
|
+
name?: string;
|
|
33
|
+
invalid?: boolean;
|
|
34
|
+
errorMessage?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
required?: boolean;
|
|
37
|
+
hideLabel?: boolean;
|
|
38
|
+
onValueChanged?: CustomEventHandler<TextFieldElement, ValueChangedDetail>;
|
|
39
|
+
} & {
|
|
40
|
+
ref?: TextFieldElement | ((element: TextFieldElement) => void) | undefined;
|
|
41
|
+
}>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { TextField as TextFieldElement } from "@unofficialbox/box-open-elements/text-field";
|
|
2
|
+
import { createWebComponent } from "./create-web-component.js";
|
|
3
|
+
TextFieldElement.register();
|
|
4
|
+
export const TextField = createWebComponent({
|
|
5
|
+
tagName: "box-text-field",
|
|
6
|
+
propertyNames: [
|
|
7
|
+
"label",
|
|
8
|
+
"value",
|
|
9
|
+
"placeholder",
|
|
10
|
+
"type", "reveal", "revealLabel", "autocomplete",
|
|
11
|
+
"disabled",
|
|
12
|
+
"readonly",
|
|
13
|
+
"name",
|
|
14
|
+
"invalid",
|
|
15
|
+
"errorMessage",
|
|
16
|
+
"description", "required", "hideLabel",
|
|
17
|
+
],
|
|
18
|
+
events: [{ propName: "onValueChanged", eventName: "value-changed" }],
|
|
19
|
+
sync: (element, props) => {
|
|
20
|
+
if (props.readonly !== undefined)
|
|
21
|
+
element.readonly = props.readonly;
|
|
22
|
+
if (props.description !== undefined)
|
|
23
|
+
element.description = props.description;
|
|
24
|
+
if (props.required !== undefined)
|
|
25
|
+
element.required = props.required;
|
|
26
|
+
if (props.hideLabel !== undefined)
|
|
27
|
+
element.hideLabel = props.hideLabel;
|
|
28
|
+
if (props.label !== undefined) {
|
|
29
|
+
element.label = props.label;
|
|
30
|
+
}
|
|
31
|
+
if (props.value !== undefined) {
|
|
32
|
+
element.value = props.value;
|
|
33
|
+
}
|
|
34
|
+
if (props.placeholder !== undefined) {
|
|
35
|
+
element.placeholder = props.placeholder;
|
|
36
|
+
}
|
|
37
|
+
if (props.type !== undefined)
|
|
38
|
+
element.type = props.type;
|
|
39
|
+
if (props.reveal !== undefined)
|
|
40
|
+
element.reveal = props.reveal;
|
|
41
|
+
if (props.revealLabel !== undefined)
|
|
42
|
+
element.revealLabel = props.revealLabel;
|
|
43
|
+
if (props.autocomplete !== undefined)
|
|
44
|
+
element.autocomplete = props.autocomplete;
|
|
45
|
+
if (props.name !== undefined) {
|
|
46
|
+
element.name = props.name;
|
|
47
|
+
}
|
|
48
|
+
if (props.errorMessage !== undefined) {
|
|
49
|
+
element.errorMessage = props.errorMessage;
|
|
50
|
+
}
|
|
51
|
+
element.disabled = Boolean(props.disabled);
|
|
52
|
+
element.invalid = Boolean(props.invalid);
|
|
53
|
+
},
|
|
54
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unofficialbox/box-open-elements-solid",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.42.2",
|
|
4
|
+
"description": "Optional native solid adapters for box-open-elements Web Components.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://unofficialbox.github.io/box-open-elements",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/unofficialbox/box-open-elements.git",
|
|
10
|
+
"directory": "packages/solid"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/unofficialbox/box-open-elements/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"solid",
|
|
17
|
+
"web-components",
|
|
18
|
+
"design-system",
|
|
19
|
+
"box"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"sideEffects": false,
|
|
23
|
+
"main": "dist/index.js",
|
|
24
|
+
"types": "dist/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
"./*": {
|
|
27
|
+
"types": "./dist/*.d.ts",
|
|
28
|
+
"import": "./dist/*.js"
|
|
29
|
+
},
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=20.9.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@unofficialbox/box-open-elements": "^0.42.2",
|
|
46
|
+
"solid-js": "^1.9.17"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc -p tsconfig.build.json",
|
|
50
|
+
"prepublishOnly": "bun run build",
|
|
51
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
52
|
+
}
|
|
53
|
+
}
|