@plastic-js/tsumiki 0.1.28 → 0.1.29

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.
@@ -0,0 +1,99 @@
1
+ import { insert, setProp, template } from "@plastic-js/plastic/jsx-runtime";
2
+ import { css } from "@emotion/css";
3
+ import { createSignal, mergeProps as mergeProps$1, onCleanup, splitProps } from "@plastic-js/plastic";
4
+ //#region src/components/BackToTop.jsx
5
+ var _tmpl2 = template("<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><title>Back to top</title><path d=\"m18 15-6-6-6 6\"></path></svg>");
6
+ var _tmpl = template("<button type=\"button\"></button>");
7
+ var read = (v) => typeof v === "function" ? v() : v;
8
+ var baseClass = css({
9
+ position: "fixed",
10
+ right: "var(--tsu-spacing-lg)",
11
+ bottom: "var(--tsu-spacing-xl)",
12
+ display: "inline-flex",
13
+ alignItems: "center",
14
+ justifyContent: "center",
15
+ width: "48px",
16
+ height: "48px",
17
+ border: "none",
18
+ borderRadius: "50%",
19
+ backgroundColor: "var(--tsu-accent-9)",
20
+ color: "var(--tsu-bg)",
21
+ boxShadow: "var(--tsu-shadow-md)",
22
+ cursor: "pointer",
23
+ userSelect: "none",
24
+ touchAction: "manipulation",
25
+ zIndex: 90,
26
+ opacity: 0,
27
+ transform: "scale(0.8)",
28
+ pointerEvents: "none",
29
+ transition: "opacity var(--tsu-transition-normal), transform var(--tsu-transition-normal)",
30
+ "&:active": { transform: "scale(0.9)" },
31
+ "&:focus-visible": {
32
+ outline: "2px solid var(--tsu-accent-8)",
33
+ outlineOffset: "2px"
34
+ }
35
+ });
36
+ var visibleClass = css({
37
+ opacity: 1,
38
+ transform: "scale(1)",
39
+ pointerEvents: "auto"
40
+ });
41
+ var iconClass = css({
42
+ display: "block",
43
+ width: "22px",
44
+ height: "22px"
45
+ });
46
+ var BackToTop = (props = {}) => {
47
+ const [local] = splitProps(mergeProps$1({ threshold: 200 }, props), [
48
+ "className",
49
+ "threshold",
50
+ "target",
51
+ "icon",
52
+ "aria-label",
53
+ "onClick"
54
+ ]);
55
+ const visible = createSignal(false);
56
+ const getEl = () => typeof local.target === "function" ? local.target() : null;
57
+ const onScroll = () => {
58
+ const el = getEl();
59
+ visible((el ? el.scrollTop : window.scrollY) > read(local.threshold));
60
+ };
61
+ onCleanup(() => {
62
+ window.removeEventListener("scroll", onScroll, true);
63
+ });
64
+ window.addEventListener("scroll", onScroll, {
65
+ capture: true,
66
+ passive: true
67
+ });
68
+ const handleClick = () => {
69
+ const el = getEl();
70
+ if (el) el.scrollTo({
71
+ top: 0,
72
+ behavior: "smooth"
73
+ });
74
+ else window.scrollTo({
75
+ top: 0,
76
+ behavior: "smooth"
77
+ });
78
+ local.onClick?.();
79
+ };
80
+ return () => {
81
+ const _el0 = _tmpl.cloneNode(true);
82
+ insert(_el0, () => local.icon || (() => {
83
+ const _el0 = _tmpl2.cloneNode(true);
84
+ setProp(_el0, "className", () => iconClass);
85
+ return _el0;
86
+ })());
87
+ setProp(_el0, "className", () => [
88
+ baseClass,
89
+ visible() && visibleClass,
90
+ local.className
91
+ ].filter(Boolean).join(" "));
92
+ setProp(_el0, "onClick", () => handleClick);
93
+ setProp(_el0, "aria-label", () => local["aria-label"] || "Back to top");
94
+ return _el0;
95
+ };
96
+ };
97
+ BackToTop.origin = { Root: "button" };
98
+ //#endregion
99
+ export { BackToTop as default };
@@ -0,0 +1,98 @@
1
+ import { insert, jsx, mergeProps, setProp, template } from "@plastic-js/plastic/jsx-runtime";
2
+ import { css } from "@emotion/css";
3
+ import { Dynamic, mergeProps as mergeProps$1, splitProps } from "@plastic-js/plastic";
4
+ //#region src/components/BottomNavigation.jsx
5
+ var _tmpl = template("<span></span>");
6
+ var read = (v) => typeof v === "function" ? v() : v;
7
+ var rootClass = css({
8
+ position: "fixed",
9
+ insetInline: "0",
10
+ bottom: "0",
11
+ display: "flex",
12
+ justifyContent: "space-around",
13
+ alignItems: "center",
14
+ height: "56px",
15
+ paddingBottom: "env(safe-area-inset-bottom)",
16
+ backgroundColor: "var(--tsu-bg)",
17
+ borderTop: "1px solid var(--tsu-neutral-6)",
18
+ zIndex: "var(--tsu-z-base)"
19
+ });
20
+ var itemClass = css({
21
+ display: "flex",
22
+ flexDirection: "column",
23
+ alignItems: "center",
24
+ gap: "var(--tsu-spacing-xxs)",
25
+ padding: "4px 12px",
26
+ border: "none",
27
+ background: "none",
28
+ fontFamily: "inherit",
29
+ color: "var(--tsu-neutral-8)",
30
+ textDecoration: "none",
31
+ cursor: "pointer",
32
+ userSelect: "none",
33
+ touchAction: "manipulation",
34
+ transition: "color var(--tsu-transition-fast)",
35
+ "&[data-active]": { color: "var(--tsu-accent-11)" }
36
+ });
37
+ var iconClass = css({
38
+ display: "flex",
39
+ alignItems: "center",
40
+ justifyContent: "center",
41
+ width: "24px",
42
+ height: "24px",
43
+ "& svg": {
44
+ width: "100%",
45
+ height: "100%"
46
+ }
47
+ });
48
+ var labelClass = css({
49
+ fontSize: "11px",
50
+ lineHeight: "14px",
51
+ fontWeight: 500
52
+ });
53
+ var BottomNavigationItem = (props = {}) => {
54
+ const [local, rest] = splitProps(props, [
55
+ "icon",
56
+ "label",
57
+ "active",
58
+ "href",
59
+ "onClick",
60
+ "className"
61
+ ]);
62
+ return jsx(Dynamic, mergeProps({ component: local.href ? "a" : "button" }, () => local.href ? { href: local.href } : { type: "button" }, {
63
+ get className() {
64
+ return [itemClass, local.className].filter(Boolean).join(" ");
65
+ },
66
+ "data-active": () => read(local.active) ? "" : void 0,
67
+ get onClick() {
68
+ return local.onClick;
69
+ },
70
+ children: [() => {
71
+ const _el0 = _tmpl.cloneNode(true);
72
+ insert(_el0, () => local.icon);
73
+ setProp(_el0, "className", () => iconClass);
74
+ return _el0;
75
+ }, () => {
76
+ const _el0 = _tmpl.cloneNode(true);
77
+ insert(_el0, () => local.label);
78
+ setProp(_el0, "className", () => labelClass);
79
+ return _el0;
80
+ }]
81
+ }));
82
+ };
83
+ var BottomNavigation = (props = {}) => {
84
+ const [local, rest] = splitProps(mergeProps$1({}, props), ["className", "children"]);
85
+ return jsx("nav", mergeProps(rest, {
86
+ get className() {
87
+ return [rootClass, local.className].filter(Boolean).join(" ");
88
+ },
89
+ children: () => local.children
90
+ }));
91
+ };
92
+ BottomNavigation.Item = BottomNavigationItem;
93
+ BottomNavigation.origin = {
94
+ Root: "nav",
95
+ Item: BottomNavigationItem
96
+ };
97
+ //#endregion
98
+ export { BottomNavigationItem, BottomNavigation as default };
@@ -116,7 +116,10 @@ var loadingMaskClass = css({
116
116
  });
117
117
  var loadingSpinnerClass = css({
118
118
  position: "relative",
119
- zIndex: 1
119
+ zIndex: 1,
120
+ display: "flex",
121
+ alignItems: "center",
122
+ justifyContent: "center"
120
123
  });
121
124
  var loadingClass = css({ pointerEvents: "none" });
122
125
  var read = (v) => typeof v === "function" ? v() : v;
@@ -0,0 +1,20 @@
1
+ import { jsx, mergeProps } from "@plastic-js/plastic/jsx-runtime";
2
+ import { css } from "@emotion/css";
3
+ import { mergeProps as mergeProps$1, splitProps } from "@plastic-js/plastic";
4
+ //#region src/components/Card.jsx
5
+ var baseClass = css({
6
+ backgroundColor: "var(--tsu-bg)",
7
+ borderRadius: "var(--tsu-radius-l2-md)"
8
+ });
9
+ var Card = (props = {}) => {
10
+ const [local, rest] = splitProps(mergeProps$1({}, props), ["className", "children"]);
11
+ return jsx("div", mergeProps(rest, {
12
+ get className() {
13
+ return [baseClass, local.className].filter(Boolean).join(" ");
14
+ },
15
+ children: () => local.children
16
+ }));
17
+ };
18
+ Card.origin = { Root: "div" };
19
+ //#endregion
20
+ export { Card as default };
@@ -1,12 +1,45 @@
1
- import { jsx, mergeProps } from "@plastic-js/plastic/jsx-runtime";
1
+ import { jsx, mergeProps, template } from "@plastic-js/plastic/jsx-runtime";
2
2
  import { css } from "@emotion/css";
3
3
  import { Collapsible } from "@plastic-js/ark";
4
4
  import { splitProps } from "@plastic-js/plastic";
5
5
  //#region src/components/Collapsible.jsx
6
+ var _tmpl = template("<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"m6 9 6 6 6-6\"></path></svg>");
6
7
  var rootClass = css({
7
8
  display: "flex",
8
9
  flexDirection: "column"
9
10
  });
11
+ var triggerClass = css({
12
+ display: "flex",
13
+ alignItems: "center",
14
+ justifyContent: "space-between",
15
+ gap: "var(--tsu-spacing-sm)",
16
+ width: "100%",
17
+ padding: "var(--tsu-comp-padding-y-sm) var(--tsu-comp-padding-x-sm)",
18
+ border: "none",
19
+ background: "var(--tsu-neutral-2)",
20
+ borderRadius: "var(--tsu-radius-l1-md)",
21
+ color: "var(--tsu-fg)",
22
+ fontSize: "var(--tsu-comp-font-size-sm)",
23
+ fontWeight: 500,
24
+ fontFamily: "inherit",
25
+ cursor: "pointer",
26
+ textAlign: "left",
27
+ touchAction: "manipulation",
28
+ transition: "background-color var(--tsu-transition-fast)",
29
+ "& svg": {
30
+ flexShrink: 0,
31
+ width: "16px",
32
+ height: "16px",
33
+ color: "var(--tsu-neutral-11)",
34
+ transition: "transform var(--tsu-transition-normal)"
35
+ },
36
+ "&[aria-expanded=\"true\"] svg": { transform: "rotate(180deg)" },
37
+ "&:disabled": {
38
+ opacity: .5,
39
+ cursor: "not-allowed"
40
+ }
41
+ });
42
+ var contentClass = css({ padding: "var(--tsu-spacing-sm) var(--tsu-spacing-md)" });
10
43
  var Collapsible$1 = (props = {}) => {
11
44
  const [local, rest] = splitProps(props, ["className", "children"]);
12
45
  return jsx(Collapsible.Root, mergeProps(rest, {
@@ -16,10 +49,25 @@ var Collapsible$1 = (props = {}) => {
16
49
  children: () => local.children
17
50
  }));
18
51
  };
52
+ var CollapsibleTrigger = (props = {}) => {
53
+ const [local, rest] = splitProps(props, ["className", "children"]);
54
+ return jsx(Collapsible.Trigger, mergeProps(rest, {
55
+ get className() {
56
+ return [triggerClass, local.className].filter(Boolean).join(" ");
57
+ },
58
+ children: [() => local.children, _tmpl.cloneNode(true)]
59
+ }));
60
+ };
61
+ var CollapsibleContent = (props = {}) => {
62
+ const [local, rest] = splitProps(props, ["className"]);
63
+ return jsx(Collapsible.Content, mergeProps(rest, { get className() {
64
+ return [contentClass, local.className].filter(Boolean).join(" ");
65
+ } }));
66
+ };
19
67
  Collapsible$1.origin = {
20
68
  Root: Collapsible.Root,
21
69
  Trigger: Collapsible.Trigger,
22
70
  Content: Collapsible.Content
23
71
  };
24
72
  //#endregion
25
- export { Collapsible$1 as default };
73
+ export { CollapsibleContent, CollapsibleTrigger, Collapsible$1 as default };
@@ -0,0 +1,150 @@
1
+ import ToggleGroup, { ToggleGroupItem } from "./ToggleGroup.js";
2
+ import { insert, jsx, mergeProps, setProp, template } from "@plastic-js/plastic/jsx-runtime";
3
+ import { css } from "@emotion/css";
4
+ import { mergeProps as mergeProps$1, splitProps } from "@plastic-js/plastic";
5
+ //#region src/components/FilterGroup.jsx
6
+ var _tmpl = template("<button type=\"button\"></button>");
7
+ var access = (v) => typeof v === "function" ? v() : v;
8
+ var sizeVars = {
9
+ xs: {
10
+ "--_tg-padding-y": "var(--tsu-comp-padding-y-xs)",
11
+ "--_tg-padding-x": "var(--tsu-comp-padding-x-xs)",
12
+ "--_tg-font-size": "var(--tsu-comp-font-size-xs)",
13
+ "--_tg-radius": "var(--tsu-radius-l1-xs)"
14
+ },
15
+ sm: {
16
+ "--_tg-padding-y": "var(--tsu-comp-padding-y-sm)",
17
+ "--_tg-padding-x": "var(--tsu-comp-padding-x-sm)",
18
+ "--_tg-font-size": "var(--tsu-comp-font-size-sm)",
19
+ "--_tg-radius": "var(--tsu-radius-l1-sm)"
20
+ },
21
+ md: {
22
+ "--_tg-padding-y": "var(--tsu-comp-padding-y-md)",
23
+ "--_tg-padding-x": "var(--tsu-comp-padding-x-md)",
24
+ "--_tg-font-size": "var(--tsu-comp-font-size-md)",
25
+ "--_tg-radius": "var(--tsu-radius-l1-md)"
26
+ },
27
+ lg: {
28
+ "--_tg-padding-y": "var(--tsu-comp-padding-y-lg)",
29
+ "--_tg-padding-x": "var(--tsu-comp-padding-x-lg)",
30
+ "--_tg-font-size": "var(--tsu-comp-font-size-lg)",
31
+ "--_tg-radius": "var(--tsu-radius-l1-lg)"
32
+ },
33
+ xl: {
34
+ "--_tg-padding-y": "var(--tsu-comp-padding-y-xl)",
35
+ "--_tg-padding-x": "var(--tsu-comp-padding-x-xl)",
36
+ "--_tg-font-size": "var(--tsu-comp-font-size-xl)",
37
+ "--_tg-radius": "var(--tsu-radius-l1-xl)"
38
+ }
39
+ };
40
+ var defaultStyle = { "--_tg-border": "var(--tsu-accent-9)" };
41
+ var rootClass = css({ display: "inline-flex" });
42
+ var allClass = css({
43
+ display: "flex",
44
+ alignItems: "center",
45
+ justifyContent: "center",
46
+ padding: "var(--_tg-padding-y, var(--tsu-comp-padding-y-md)) var(--_tg-padding-x, var(--tsu-comp-padding-x-md))",
47
+ border: "1px solid var(--_tg-border)",
48
+ borderRight: "none",
49
+ borderTopLeftRadius: "var(--_tg-radius, var(--tsu-radius-l1-md))",
50
+ borderBottomLeftRadius: "var(--_tg-radius, var(--tsu-radius-l1-md))",
51
+ background: "transparent",
52
+ color: "var(--tsu-neutral-11)",
53
+ fontSize: "var(--_tg-font-size, var(--tsu-comp-font-size-md))",
54
+ fontWeight: 500,
55
+ fontFamily: "inherit",
56
+ cursor: "pointer",
57
+ touchAction: "manipulation",
58
+ transition: "background-color var(--tsu-transition-fast), color var(--tsu-transition-fast)",
59
+ "&[data-state=\"on\"]": {
60
+ backgroundColor: "var(--tsu-accent-9)",
61
+ color: "var(--tsu-bg)"
62
+ },
63
+ "&:disabled": {
64
+ opacity: .5,
65
+ cursor: "not-allowed"
66
+ }
67
+ });
68
+ var tgStyle = {
69
+ borderTopLeftRadius: "0",
70
+ borderBottomLeftRadius: "0"
71
+ };
72
+ var FilterGroup = (props = {}) => {
73
+ const [local, rest] = splitProps(mergeProps$1({
74
+ size: "md",
75
+ allLabel: "All",
76
+ items: []
77
+ }, props), [
78
+ "className",
79
+ "items",
80
+ "value",
81
+ "onValueChange",
82
+ "allLabel",
83
+ "size",
84
+ "buttonClass",
85
+ "groupClass"
86
+ ]);
87
+ const value = () => access(local.value) ?? [];
88
+ const allActive = () => value().length === 0;
89
+ const emit = (val) => {
90
+ local.onValueChange?.(val);
91
+ };
92
+ const handleAllClick = () => {
93
+ if (allActive()) return;
94
+ emit([]);
95
+ };
96
+ const handleChange = (value) => emit(value);
97
+ return jsx("div", mergeProps(rest, {
98
+ get className() {
99
+ return [rootClass, local.className].filter(Boolean).join(" ");
100
+ },
101
+ get style() {
102
+ return {
103
+ ...defaultStyle,
104
+ ...sizeVars[local.size]
105
+ };
106
+ },
107
+ children: [() => {
108
+ const _el0 = _tmpl.cloneNode(true);
109
+ insert(_el0, () => local.allLabel);
110
+ setProp(_el0, "className", () => [allClass, local.buttonClass].filter(Boolean).join(" "));
111
+ setProp(_el0, "data-state", () => allActive() ? "on" : "off");
112
+ setProp(_el0, "onClick", () => handleAllClick);
113
+ return _el0;
114
+ }, jsx(ToggleGroup, mergeProps({
115
+ multiple: true,
116
+ get size() {
117
+ return local.size;
118
+ },
119
+ get value() {
120
+ return allActive() ? [] : value();
121
+ },
122
+ onValueChange: handleChange,
123
+ get className() {
124
+ return local.groupClass;
125
+ },
126
+ style: tgStyle,
127
+ children: () => local.items.map((item) => jsx(ToggleGroupItem, mergeProps({
128
+ get key() {
129
+ return item.value;
130
+ },
131
+ get value() {
132
+ return item.value;
133
+ },
134
+ get disabled() {
135
+ return item.disabled;
136
+ },
137
+ get className() {
138
+ return local.buttonClass;
139
+ },
140
+ children: () => item.label
141
+ })))
142
+ }))]
143
+ }));
144
+ };
145
+ FilterGroup.origin = {
146
+ ToggleGroup,
147
+ ToggleGroupItem
148
+ };
149
+ //#endregion
150
+ export { FilterGroup as default };
@@ -0,0 +1,32 @@
1
+ import { jsx, mergeProps } from "@plastic-js/plastic/jsx-runtime";
2
+ import { css } from "@emotion/css";
3
+ import { mergeProps as mergeProps$1, splitProps } from "@plastic-js/plastic";
4
+ //#region src/components/Link.jsx
5
+ var baseClass = css({
6
+ color: "var(--tsu-accent-11)",
7
+ textDecoration: "none",
8
+ cursor: "pointer",
9
+ fontWeight: 500,
10
+ transition: "color var(--tsu-transition-fast), text-decoration-color var(--tsu-transition-fast)",
11
+ "&:hover": {
12
+ textDecoration: "underline",
13
+ textDecorationColor: "var(--tsu-accent-6)"
14
+ },
15
+ "&:focus-visible": {
16
+ outline: "2px solid var(--tsu-focus-border)",
17
+ outlineOffset: "2px",
18
+ borderRadius: "2px"
19
+ }
20
+ });
21
+ var Link = (props = {}) => {
22
+ const [local, rest] = splitProps(mergeProps$1({}, props), ["className", "children"]);
23
+ return jsx("a", mergeProps(rest, {
24
+ get className() {
25
+ return [baseClass, local.className].filter(Boolean).join(" ");
26
+ },
27
+ children: () => local.children
28
+ }));
29
+ };
30
+ Link.origin = { Root: "a" };
31
+ //#endregion
32
+ export { Link as default };
@@ -0,0 +1,30 @@
1
+ import { jsx, mergeProps } from "@plastic-js/plastic/jsx-runtime";
2
+ import { css } from "@emotion/css";
3
+ import { mergeProps as mergeProps$1, splitProps } from "@plastic-js/plastic";
4
+ //#region src/components/SafeArea.jsx
5
+ var read = (v) => typeof v === "function" ? v() : v;
6
+ var baseClass = css({ boxSizing: "border-box" });
7
+ var positionClasses = {
8
+ top: css({ paddingTop: "env(safe-area-inset-top)" }),
9
+ bottom: css({ paddingBottom: "env(safe-area-inset-bottom)" }),
10
+ left: css({ paddingLeft: "env(safe-area-inset-left)" }),
11
+ right: css({ paddingRight: "env(safe-area-inset-right)" })
12
+ };
13
+ var SafeArea = (props = {}) => {
14
+ const [local, rest] = splitProps(mergeProps$1({ position: "top" }, props), [
15
+ "className",
16
+ "children",
17
+ "position"
18
+ ]);
19
+ return jsx("div", mergeProps(rest, {
20
+ className: () => [
21
+ baseClass,
22
+ positionClasses[read(local.position)],
23
+ local.className
24
+ ].filter(Boolean).join(" "),
25
+ children: () => local.children
26
+ }));
27
+ };
28
+ SafeArea.origin = { Root: "div" };
29
+ //#endregion
30
+ export { SafeArea as default };
@@ -352,9 +352,7 @@ var Content = () => {
352
352
  };
353
353
  return jsx("div", mergeProps(() => part("positioner"), {
354
354
  "aria-hidden": () => !ctx.open(),
355
- get className() {
356
- return `${overlayClass} ${ctx.open() ? openClass : ""}`;
357
- },
355
+ className: () => `${overlayClass} ${ctx.open() ? openClass : ""}`,
358
356
  children: [jsx("div", mergeProps(() => part("backdrop"), {
359
357
  get className() {
360
358
  return `${backdropClass} ${ctx.backdropClassName ?? ""}`;
@@ -236,4 +236,4 @@ SelectPc.origin = {
236
236
  HiddenSelect: Select.HiddenSelect
237
237
  };
238
238
  //#endregion
239
- export { SelectPc as default };
239
+ export { SelectItem, SelectPc as default };
@@ -0,0 +1,35 @@
1
+ import { jsx, mergeProps } from "@plastic-js/plastic/jsx-runtime";
2
+ import { css } from "@emotion/css";
3
+ import { mergeProps as mergeProps$1, splitProps } from "@plastic-js/plastic";
4
+ //#region src/components/StickyHeader.jsx
5
+ var read = (v) => typeof v === "function" ? v() : v;
6
+ var baseClass = css({
7
+ position: "sticky",
8
+ zIndex: "var(--tsu-z-dropdown)",
9
+ backgroundColor: "var(--tsu-bg)"
10
+ });
11
+ var shadowClass = css({ boxShadow: "var(--tsu-shadow-sm)" });
12
+ var StickyHeader = (props = {}) => {
13
+ const [local, rest] = splitProps(mergeProps$1({ offsetTop: 0 }, props), [
14
+ "className",
15
+ "children",
16
+ "offsetTop",
17
+ "shadow",
18
+ "style"
19
+ ]);
20
+ return jsx("div", mergeProps(rest, {
21
+ className: () => [
22
+ baseClass,
23
+ read(local.shadow) && shadowClass,
24
+ local.className
25
+ ].filter(Boolean).join(" "),
26
+ style: () => ({
27
+ top: `${read(local.offsetTop)}px`,
28
+ ...typeof local.style === "object" && local.style ? local.style : void 0
29
+ }),
30
+ children: () => local.children
31
+ }));
32
+ };
33
+ StickyHeader.origin = { Root: "div" };
34
+ //#endregion
35
+ export { StickyHeader as default };
@@ -112,5 +112,11 @@ TreeView$1.origin = {
112
112
  Label: TreeView.Label,
113
113
  Tree: TreeView.Tree
114
114
  };
115
+ TreeView$1.treeViewPart = TreeView.Root.treeViewPart;
116
+ TreeViewBranch.treeViewPart = TreeView.Branch.treeViewPart;
117
+ TreeViewBranchTrigger.treeViewPart = TreeView.BranchTrigger.treeViewPart;
118
+ TreeViewBranchContent.treeViewPart = TreeView.BranchContent.treeViewPart;
119
+ TreeViewBranchControl.treeViewPart = TreeView.BranchControl.treeViewPart;
120
+ TreeViewItem.treeViewPart = TreeView.Item.treeViewPart;
115
121
  //#endregion
116
122
  export { TreeViewBranch, TreeViewBranchContent, TreeViewBranchControl, TreeViewBranchTrigger, TreeViewItem, TreeView$1 as default };
package/dist/index.js CHANGED
@@ -1,16 +1,19 @@
1
1
  import AccordionRoot, { AccordionContent, AccordionItem, AccordionTrigger } from "./components/Accordion.js";
2
2
  import Avatar, { AvatarFallback, AvatarImage } from "./components/Avatar.js";
3
+ import BackToTop from "./components/BackToTop.js";
4
+ import BottomNavigation, { BottomNavigationItem } from "./components/BottomNavigation.js";
3
5
  import Portal_default from "./components/Portal.js";
4
6
  import BottomSheet from "./components/BottomSheet.js";
5
7
  import Spinner from "./components/Spinner.js";
6
8
  import Button from "./components/Button.js";
9
+ import Card from "./components/Card.js";
7
10
  import Input$1 from "./components/Input.js";
8
11
  import CardNumberInput from "./components/CardNumberInput.js";
9
12
  import Carousel_default, { CarouselAutoplayTrigger, CarouselControl, CarouselIndicator, CarouselIndicatorGroup, CarouselItem, CarouselItemGroup, CarouselNextTrigger, CarouselPrevTrigger, CarouselProgressText } from "./components/Carousel.js";
10
13
  import Checkbox from "./components/Checkbox.js";
11
14
  import Clipboard from "./components/Clipboard.js";
12
15
  import CloseButton from "./components/CloseButton.js";
13
- import Collapsible from "./components/Collapsible.js";
16
+ import Collapsible, { CollapsibleContent, CollapsibleTrigger } from "./components/Collapsible.js";
14
17
  import ColorPicker from "./components/ColorPicker.js";
15
18
  import Root, { ComboboxContent, ComboboxItem, Input } from "./components/Combobox.js";
16
19
  import Icon from "./components/Icon.js";
@@ -23,6 +26,7 @@ import Fieldset from "./components/Fieldset.js";
23
26
  import FileUpload, { FileUploadClearTrigger, FileUploadItem, FileUploadItemGroup } from "./components/FileUpload.js";
24
27
  import FocusTrap_default from "./components/FocusTrap.js";
25
28
  import Listbox from "./components/Listbox.js";
29
+ import Link from "./components/Link.js";
26
30
  import Menu, { MenuContent, MenuItem, MenuSeparator, MenuTrigger } from "./components/Menu.js";
27
31
  import MoneyInput from "./components/MoneyInput.js";
28
32
  import NumberInput from "./components/NumberInput.js";
@@ -32,14 +36,16 @@ import Presence_default from "./components/Presence.js";
32
36
  import Progress, { ProgressLabel } from "./components/Progress.js";
33
37
  import RadioGroup from "./components/RadioGroup.js";
34
38
  import RatingGroup from "./components/RatingGroup.js";
39
+ import SafeArea from "./components/SafeArea.js";
35
40
  import SearchInput from "./components/SearchInput.js";
36
41
  import Select, { SelectTrigger } from "./components/Select.js";
37
- import SelectPc from "./components/SelectPc.js";
42
+ import SelectPc, { SelectItem } from "./components/SelectPc.js";
38
43
  import SignaturePad, { ClearTrigger } from "./components/SignaturePad.js";
39
44
  import Skeleton from "./components/Skeleton.js";
40
45
  import Slider from "./components/Slider.js";
41
46
  import Splitter, { SplitterPanel, SplitterResizeTrigger, SplitterResizeTriggerIndicator } from "./components/Splitter.js";
42
47
  import Steps from "./components/Steps.js";
48
+ import StickyHeader from "./components/StickyHeader.js";
43
49
  import SwipeReveal from "./components/SwipeReveal.js";
44
50
  import Switch from "./components/Switch.js";
45
51
  import Tabs from "./components/Tabs.js";
@@ -47,6 +53,7 @@ import TagsInput from "./components/TagsInput.js";
47
53
  import Toast, { ToastCloseTrigger, ToastDescription, ToastIcon, ToastTitle, ToastToaster, createToaster } from "./components/Toast.js";
48
54
  import Toggle from "./components/Toggle.js";
49
55
  import ToggleGroup, { ToggleGroupItem } from "./components/ToggleGroup.js";
56
+ import FilterGroup from "./components/FilterGroup.js";
50
57
  import Tour, { TourCloseTrigger, TourContent } from "./components/Tour.js";
51
58
  import TreeView, { TreeViewBranch, TreeViewBranchContent, TreeViewBranchControl, TreeViewBranchTrigger, TreeViewItem } from "./components/TreeView.js";
52
- export { AccordionRoot as Accordion, AccordionContent, AccordionItem, AccordionTrigger, Avatar, AvatarFallback, AvatarImage, BottomSheet, Button, CardNumberInput, Carousel_default as Carousel, CarouselAutoplayTrigger, CarouselControl, CarouselIndicator, CarouselIndicatorGroup, CarouselItem, CarouselItemGroup, CarouselNextTrigger, CarouselPrevTrigger, CarouselProgressText, Checkbox, ClearTrigger, Clipboard, CloseButton, Collapsible, ColorPicker, Root as Combobox, ComboboxContent, Input as ComboboxInput, ComboboxItem, ConfirmDialog, DateInput, Dialog, Root$1 as Drawer, DrawerContent, DrawerTrigger, Field, Fieldset, FileUpload, FileUploadClearTrigger, FileUploadItem, FileUploadItemGroup, FocusTrap_default as FocusTrap, Icon, Input$1 as Input, Listbox, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, MoneyInput, NumberInput, Pagination, Popover, Portal_default as Portal, Presence_default as Presence, Progress, ProgressLabel, RadioGroup, RatingGroup, SearchInput, Select, SelectPc, SelectTrigger, SignaturePad, Skeleton, Slider, Spinner, Splitter, SplitterPanel, SplitterResizeTrigger, SplitterResizeTriggerIndicator, Steps, SwipeReveal, Switch, Tabs, TagsInput, Toast, ToastCloseTrigger, ToastDescription, ToastIcon, ToastTitle, ToastToaster, Toggle, ToggleGroup, ToggleGroupItem, Tour, TourCloseTrigger, TourContent, TreeView, TreeViewBranch, TreeViewBranchContent, TreeViewBranchControl, TreeViewBranchTrigger, TreeViewItem, confirm, createToaster };
59
+ export { AccordionRoot as Accordion, AccordionContent, AccordionItem, AccordionTrigger, Avatar, AvatarFallback, AvatarImage, BackToTop, BottomNavigation, BottomNavigationItem, BottomSheet, Button, Card, CardNumberInput, Carousel_default as Carousel, CarouselAutoplayTrigger, CarouselControl, CarouselIndicator, CarouselIndicatorGroup, CarouselItem, CarouselItemGroup, CarouselNextTrigger, CarouselPrevTrigger, CarouselProgressText, Checkbox, ClearTrigger, Clipboard, CloseButton, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorPicker, Root as Combobox, ComboboxContent, Input as ComboboxInput, ComboboxItem, ConfirmDialog, DateInput, Dialog, Root$1 as Drawer, DrawerContent, DrawerTrigger, Field, Fieldset, FileUpload, FileUploadClearTrigger, FileUploadItem, FileUploadItemGroup, FilterGroup, FocusTrap_default as FocusTrap, Icon, Input$1 as Input, Link, Listbox, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, MoneyInput, NumberInput, Pagination, Popover, Portal_default as Portal, Presence_default as Presence, Progress, ProgressLabel, RadioGroup, RatingGroup, SafeArea, SearchInput, Select, SelectItem, SelectPc, SelectTrigger, SignaturePad, Skeleton, Slider, Spinner, Splitter, SplitterPanel, SplitterResizeTrigger, SplitterResizeTriggerIndicator, Steps, StickyHeader, SwipeReveal, Switch, Tabs, TagsInput, Toast, ToastCloseTrigger, ToastDescription, ToastIcon, ToastTitle, ToastToaster, Toggle, ToggleGroup, ToggleGroupItem, Tour, TourCloseTrigger, TourContent, TreeView, TreeViewBranch, TreeViewBranchContent, TreeViewBranchControl, TreeViewBranchTrigger, TreeViewItem, confirm, createToaster };
package/docs/api.md CHANGED
@@ -57,10 +57,10 @@ A labeled field wrapper combining a label, an error message and helper text, bac
57
57
  **Exports:** `Field` · Escape hatch: `Field.origin.{Root, Label, Input, Textarea, Select, HelperText, ErrorText, RequiredIndicator, Item}`
58
58
 
59
59
  | Prop | Type | Default | Description |
60
- |---|---|---|---|
61
- | `label` | `string` | `''` | Field label text. |
62
- | `error` | `string` | `''` | Error message; when non-empty the field renders in its error state. |
63
- | `helper` | `string` | `''` | Helper text below the control. |
60
+ |---|---|---|---|---|
61
+ | `label` | `string \| node` | `''` | Label content — any text or JSX. Styling is fixed. |
62
+ | `error` | `string \| node` | `''` | Error content; when non-empty the field renders in its error state. Styling is fixed. |
63
+ | `helper` | `string \| node` | `''` | Helper content below the control. Styling is fixed. |
64
64
  | `required` | `boolean` | `false` | Marks the label with a required indicator. |
65
65
  | `compact` | `boolean` | `false` | Renders in a compact (smaller) layout. |
66
66
  | `invalid` | `boolean` | `false` | Error state (also implied by a non-empty `error`). |
@@ -77,9 +77,9 @@ Groups several `Field`s with a legend, backed by `ArkFieldset` (native `<fieldse
77
77
  **Exports:** `Fieldset` · Escape hatch: `Fieldset.origin.{Root, Legend, HelperText, ErrorText}`
78
78
 
79
79
  | Prop | Type | Default | Description |
80
- |---|---|---|---|
81
- | `legend` | `string` | `''` | Fieldset legend text. |
82
- | `helper` | `string` | `''` | Helper text below the fields. |
80
+ |---|---|---|---|---|
81
+ | `legend` | `string \| node` | `''` | Legend content — any text or JSX. Styling is fixed. |
82
+ | `helper` | `string \| node` | `''` | Helper content below the fields. Styling is fixed. |
83
83
  | `children` | `node` | — | `Field` components to group. |
84
84
 
85
85
  Passthrough: Ark `Fieldset.Root` props (`disabled`, `invalid`, …).
@@ -267,6 +267,23 @@ Passthrough: Ark `Root` props (`pressed`, `onPressedChange`, …).
267
267
  | `size` | `string` | `md` | See size values. |
268
268
  | `children` | `node` | — | `ToggleGroupItem` elements. |
269
269
 
270
+ ### FilterGroup
271
+
272
+ Multi-select filter bar built on `ToggleGroup`. Renders an "All" toggle; selecting any item clears it, and an empty selection maps back to "All".
273
+
274
+ **Exports:** `FilterGroup`
275
+
276
+ | Prop | Type | Default | Description |
277
+ |---|---|---|---|
278
+ | `value` | `array \| (() => array)` | — | Selected item values (controlled). |
279
+ | `onValueChange` | `(value) => void` | — | Called with the new selection array. |
280
+ | `items` | `array` | `[]` | Filter items (`{ value, label, disabled? }`). |
281
+ | `allLabel` | `string` | `'All'` | Label for the clear/All toggle. |
282
+ | `size` | `string` | `md` | See size values. |
283
+ | `buttonClass` | `string` | — | Class applied to every button. |
284
+ | `groupClass` | `string` | — | Class applied to the inner `ToggleGroup`. |
285
+ | `className` | `string` | — | Root class. |
286
+
270
287
  ### RadioGroup
271
288
 
272
289
  **Exports:** `RadioGroup` · Escape hatch: `RadioGroup.origin.{Root, Label, Item, ItemControl, ItemText, ItemHiddenInput, Indicator}`
@@ -323,7 +340,7 @@ Mobile-optimized bottom-sheet select (draggable sheet overlay).
323
340
 
324
341
  Desktop (popover-style) select built on Ark `Select`.
325
342
 
326
- **Exports:** `SelectPc` · Escape hatch: `SelectPc.origin.{Root, Trigger, Indicator, Positioner, Content, List, Item, ItemText, ValueText, HiddenSelect}`
343
+ **Exports:** `SelectPc`, `SelectItem` · Escape hatch: `SelectPc.origin.{Root, Trigger, Indicator, Positioner, Content, List, Item, ItemText, ValueText, HiddenSelect}`
327
344
 
328
345
  | Prop | Type | Default | Description |
329
346
  |---|---|---|---|
@@ -332,7 +349,7 @@ Desktop (popover-style) select built on Ark `Select`.
332
349
  | `disabled` | `boolean` | `false` | Disabled. |
333
350
  | `invalid` | `boolean` | `false` | Error state. |
334
351
  | `positioning` | `object` | `{ sameWidth: true }` | Positioning options. |
335
- | `children` | `node` | — | `SelectPc.origin.Item` elements or custom content. |
352
+ | `children` | `node` | — | `SelectItem` elements or custom content. |
336
353
 
337
354
  Passthrough: Ark `Root` props (`value`, `onValueChange`, `collection`, …). Note: unlike `Select`, it is **not** controlled-only at the tsumiki level — state flows through the Ark props.
338
355
 
@@ -411,18 +428,105 @@ Passthrough: Ark `Root` props (`value`, `onValueChange`, `orientation`, …).
411
428
 
412
429
  Passthrough: Ark `Root` props (`count`, `pageSize`, `page`, `onPageChange`, …).
413
430
 
431
+ ### BottomNavigation
432
+
433
+ Fixed bottom navigation bar with icons and labels.
434
+
435
+ **Exports:** `BottomNavigation`, `BottomNavigationItem`
436
+
437
+ | Prop | Type | Default | Description |
438
+ |---|---|---|---|
439
+ | `className` | `string` | — | Root class. |
440
+ | `children` | `node` | — | `BottomNavigationItem` elements. |
441
+
442
+ `BottomNavigationItem`:
443
+
444
+ | Prop | Type | Default | Description |
445
+ |---|---|---|---|
446
+ | `icon` | `node` | — | Icon content. |
447
+ | `label` | `string` | — | Item label. |
448
+ | `active` | `boolean` | `false` | Active state. |
449
+ | `href` | `string` | — | When set, renders an `<a>` instead of a `<button>`. |
450
+ | `onClick` | `() => void` | — | Click handler. |
451
+ | `className` | `string` | — | Item class. |
452
+
453
+ ### BackToTop
454
+
455
+ Floating scroll-to-top button that appears after scrolling past a threshold.
456
+
457
+ **Exports:** `BackToTop`
458
+
459
+ | Prop | Type | Default | Description |
460
+ |---|---|---|---|
461
+ | `threshold` | `number` | `200` | Scroll offset (px) at which the button appears. |
462
+ | `target` | `() => Element` | — | Scroll container. When omitted, uses the window. |
463
+ | `icon` | `node` | — | Custom button icon. |
464
+ | `onClick` | `() => void` | — | Click callback. |
465
+ | `className` | `string` | — | Button class. |
466
+
414
467
  ---
415
468
 
416
469
  ## Content & Layout
417
470
 
418
471
  ### Collapsible
419
472
 
420
- **Exports:** `Collapsible` · Escape hatch: `Collapsible.origin.{Root, Trigger, Content}`
473
+ **Exports:** `Collapsible`, `CollapsibleTrigger`, `CollapsibleContent` · Escape hatch: `Collapsible.origin.{Root, Trigger, Content}`
421
474
 
422
475
  | Prop | Type | Default | Description |
423
476
  |---|---|---|---|
424
477
  | `className` | `string` | — | Root class. |
425
- | `children` | `node` | — | `Trigger` / `Content` elements. |
478
+ | `children` | `node` | — | `CollapsibleTrigger` / `CollapsibleContent` elements. |
479
+
480
+ ### Card
481
+
482
+ Container with themed background and border radius.
483
+
484
+ **Exports:** `Card`
485
+
486
+ | Prop | Type | Default | Description |
487
+ |---|---|---|---|
488
+ | `className` | `string` | — | Root class. |
489
+ | `children` | `node` | — | Content. |
490
+
491
+ Passthrough: `div` DOM props (`style`, `onClick`, …).
492
+
493
+ ### Link
494
+
495
+ Styled anchor.
496
+
497
+ **Exports:** `Link`
498
+
499
+ | Prop | Type | Default | Description |
500
+ |---|---|---|---|
501
+ | `className` | `string` | — | Root class. |
502
+ | `children` | `node` | — | Content. |
503
+
504
+ Passthrough: native `<a>` props (`href`, `target`, `rel`, …).
505
+
506
+ ### SafeArea
507
+
508
+ Adds device safe-area inset padding.
509
+
510
+ **Exports:** `SafeArea`
511
+
512
+ | Prop | Type | Default | Description |
513
+ |---|---|---|---|
514
+ | `position` | `string` | `'top'` | `'top' \| 'bottom' \| 'left' \| 'right'`. |
515
+ | `className` | `string` | — | Root class. |
516
+ | `children` | `node` | — | Content. |
517
+
518
+ ### StickyHeader
519
+
520
+ Header that sticks to the top while scrolling.
521
+
522
+ **Exports:** `StickyHeader`
523
+
524
+ | Prop | Type | Default | Description |
525
+ |---|---|---|---|
526
+ | `offsetTop` | `number` | `0` | Sticky top offset (px). |
527
+ | `shadow` | `boolean` | `false` | Add a drop shadow when stuck. |
528
+ | `className` | `string` | — | Root class. |
529
+ | `children` | `node` | — | Content. |
426
530
 
427
531
  ### Splitter
428
532
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plastic-js/tsumiki",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "A UI component library for Plastic JS.",
5
5
  "license": "MIT",
6
6
  "author": "tigre",