@stamcat/craftsman 0.0.27-alpha.9 → 0.0.28

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.
Files changed (180) hide show
  1. package/AGENTS.md +21 -403
  2. package/Components.esm.js +62 -11
  3. package/README.md +63 -12
  4. package/Styles.esm.js +7 -7
  5. package/Utilities.esm.js +2 -2
  6. package/_virtual/_rolldown/runtime.esm.js +18 -6
  7. package/package.json +51 -3
  8. package/src/components/Button/AGENTS.md +65 -0
  9. package/src/components/Button/Button.d.ts +1 -1
  10. package/src/components/Button/Button.esm.js +11 -17
  11. package/src/components/Carousel/AGENTS.md +41 -0
  12. package/src/components/Carousel/Carousel.css +1 -0
  13. package/src/components/Carousel/Carousel.d.ts +11 -0
  14. package/src/components/Carousel/Carousel.scss +34 -0
  15. package/src/components/Carousel/Carousel2.esm.js +75 -0
  16. package/src/components/Checkbox/AGENTS.md +34 -0
  17. package/src/components/Checkbox/Checkbox.d.ts +8 -0
  18. package/src/components/Checkbox/Checkbox.esm.js +18 -0
  19. package/src/components/DatePicker/AGENTS.md +36 -0
  20. package/src/components/DatePicker/DatePicker.css +1 -0
  21. package/src/components/DatePicker/DatePicker.d.ts +8 -0
  22. package/src/components/DatePicker/DatePicker.scss +61 -0
  23. package/src/components/DatePicker/DatePicker2.esm.js +29 -0
  24. package/src/components/DatePicker/ReactCalendar.css +1 -0
  25. package/src/components/DatePicker/ReactCalendar.scss +158 -0
  26. package/src/components/DatePicker/_DatePicker.scss +73 -0
  27. package/src/components/DateRangePicker/AGENTS.md +38 -0
  28. package/src/components/DateRangePicker/DateRangePicker.css +1 -0
  29. package/src/components/DateRangePicker/DateRangePicker.d.ts +8 -0
  30. package/src/components/DateRangePicker/DateRangePicker.scss +62 -0
  31. package/src/components/DateRangePicker/DateRangePicker2.esm.js +29 -0
  32. package/src/components/DateTimePicker/AGENTS.md +41 -0
  33. package/src/components/DateTimePicker/DateTimePicker.css +1 -0
  34. package/src/components/DateTimePicker/DateTimePicker.d.ts +13 -0
  35. package/src/components/DateTimePicker/DateTimePicker.scss +86 -0
  36. package/src/components/DateTimePicker/DateTimePicker2.esm.js +82 -0
  37. package/src/components/Icons/IconAmazonPay.d.ts +2 -0
  38. package/src/components/Icons/IconAmazonPay.esm.js +76 -0
  39. package/src/components/Icons/IconAmex.d.ts +2 -0
  40. package/src/components/Icons/IconAmex.esm.js +87 -0
  41. package/src/components/Icons/IconApplePay.d.ts +2 -0
  42. package/src/components/Icons/IconApplePay.esm.js +26 -0
  43. package/src/components/Icons/IconDiscover.d.ts +2 -0
  44. package/src/components/Icons/IconDiscover.esm.js +129 -0
  45. package/src/components/Icons/IconGooglePay.d.ts +2 -0
  46. package/src/components/Icons/IconGooglePay.esm.js +64 -0
  47. package/src/components/Icons/IconMaestro.d.ts +2 -0
  48. package/src/components/Icons/IconMaestro.esm.js +38 -0
  49. package/src/components/Icons/IconMastercard.d.ts +2 -0
  50. package/src/components/Icons/IconMastercard.esm.js +27 -0
  51. package/src/components/Icons/IconPayPal.d.ts +2 -0
  52. package/src/components/Icons/IconPayPal.esm.js +52 -0
  53. package/src/components/Icons/IconSepa.d.ts +2 -0
  54. package/src/components/Icons/IconSepa.esm.js +272 -0
  55. package/src/components/Icons/IconShopPay.d.ts +2 -0
  56. package/src/components/Icons/IconShopPay.esm.js +35 -0
  57. package/src/components/Icons/IconSquare.d.ts +2 -0
  58. package/src/components/Icons/IconSquare.esm.js +11 -0
  59. package/src/components/Icons/IconStripe.d.ts +2 -0
  60. package/src/components/Icons/IconStripe.esm.js +57 -0
  61. package/src/components/Icons/IconUnionPay.d.ts +2 -0
  62. package/src/components/Icons/IconUnionPay.esm.js +28 -0
  63. package/src/components/Icons/IconVenmo.d.ts +2 -0
  64. package/src/components/Icons/IconVenmo.esm.js +21 -0
  65. package/src/components/Icons/IconVisa.d.ts +2 -0
  66. package/src/components/Icons/IconVisa.esm.js +14 -0
  67. package/src/components/Icons/index.d.ts +15 -0
  68. package/src/components/Icons/index.esm.js +16 -0
  69. package/src/components/Icons/types.d.ts +4 -0
  70. package/src/components/Input/AGENTS.md +30 -0
  71. package/src/components/Input/Input.css +1 -1
  72. package/src/components/Input/Input.scss +108 -95
  73. package/src/components/Input/Input2.esm.js +27 -18
  74. package/src/components/Input/InputWrapper.d.ts +1 -0
  75. package/src/components/InputNumber/AGENTS.md +37 -0
  76. package/src/components/InputNumber/InputNumber.css +1 -0
  77. package/src/components/InputNumber/InputNumber.d.ts +10 -0
  78. package/src/components/InputNumber/InputNumber.scss +29 -0
  79. package/src/components/InputNumber/InputNumber2.esm.js +36 -0
  80. package/src/components/InputPassword/AGENTS.md +29 -0
  81. package/src/components/{Input → InputPassword}/InputPassword.d.ts +1 -1
  82. package/src/components/InputPassword/InputPassword.esm.js +30 -0
  83. package/src/components/InputPhone/AGENTS.md +35 -0
  84. package/src/components/InputPhone/InputPhone.css +1 -0
  85. package/src/components/{Input → InputPhone}/InputPhone.d.ts +1 -1
  86. package/src/components/InputPhone/InputPhone.scss +266 -0
  87. package/src/components/{Input/InputPhone.esm.js → InputPhone/InputPhone2.esm.js} +4 -4
  88. package/src/components/Loader/AGENTS.md +31 -0
  89. package/src/components/Loader/Loader.esm.js +1 -1
  90. package/src/components/Loader/types.d.ts +1 -1
  91. package/src/components/Modal/AGENTS.md +47 -0
  92. package/src/components/Modal/Modal.css +1 -0
  93. package/src/components/Modal/Modal.scss +150 -0
  94. package/src/components/Modal/Modal2.esm.js +53 -0
  95. package/src/components/Notice/AGENTS.md +42 -0
  96. package/src/components/Notice/Notice.css +1 -0
  97. package/src/components/Notice/Notice.d.ts +13 -0
  98. package/src/components/Notice/Notice.scss +76 -0
  99. package/src/components/Notice/Notice2.esm.js +56 -0
  100. package/src/components/Pagination/AGENTS.md +38 -0
  101. package/src/components/Pagination/Pagination.css +1 -0
  102. package/src/components/Pagination/Pagination.d.ts +10 -0
  103. package/src/components/Pagination/Pagination.scss +22 -0
  104. package/src/components/Pagination/Pagination2.esm.js +64 -0
  105. package/src/components/RadioButton/AGENTS.md +44 -0
  106. package/src/components/RadioButton/RadioButton.d.ts +9 -0
  107. package/src/components/RadioButton/RadioButton.esm.js +18 -0
  108. package/src/components/Select/AGENTS.md +36 -0
  109. package/src/components/SortableList/AGENTS.md +45 -0
  110. package/src/components/SortableList/ListItem.d.ts +10 -0
  111. package/src/components/SortableList/ListItem.esm.js +67 -0
  112. package/src/components/SortableList/SortableList.css +1 -0
  113. package/src/components/SortableList/SortableList.d.ts +23 -0
  114. package/src/components/SortableList/SortableList.scss +41 -0
  115. package/src/components/SortableList/SortableList2.esm.js +54 -0
  116. package/src/components/SortableList/utilities.d.ts +7 -0
  117. package/src/components/SortableList/utilities.esm.js +4 -0
  118. package/src/components/Text/AGENTS.md +32 -0
  119. package/src/components/Text/Text.css +1 -1
  120. package/src/components/Text/Text.scss +2 -2
  121. package/src/components/Textarea/AGENTS.md +32 -0
  122. package/src/components/{Input → Textarea}/Textarea.d.ts +1 -1
  123. package/src/components/Textarea/Textarea.esm.js +23 -0
  124. package/src/components/TimePicker/AGENTS.md +42 -0
  125. package/src/components/TimePicker/TimePicker.css +1 -0
  126. package/src/components/TimePicker/TimePicker.d.ts +13 -0
  127. package/src/components/TimePicker/TimePicker.scss +226 -0
  128. package/src/components/TimePicker/TimePicker2.esm.js +98 -0
  129. package/src/components/TimePicker/TimePickerDisplay.d.ts +16 -0
  130. package/src/components/TimePicker/TimePickerDisplay.esm.js +54 -0
  131. package/src/components/TimePicker/TimePickerWheel.d.ts +13 -0
  132. package/src/components/TimePicker/TimePickerWheel.esm.js +61 -0
  133. package/src/components/TimePicker/constants.d.ts +7 -0
  134. package/src/components/TimePicker/constants.esm.js +3 -0
  135. package/src/components/TimePicker/utilities.d.ts +15 -0
  136. package/src/components/TimePicker/utilities.esm.js +20 -0
  137. package/src/components/Toggle/AGENTS.md +33 -0
  138. package/src/components/Toggle/Toggle.css +1 -0
  139. package/src/components/Toggle/Toggle.d.ts +5 -0
  140. package/src/components/Toggle/Toggle.scss +64 -0
  141. package/src/components/Toggle/Toggle2.esm.js +19 -0
  142. package/src/components/Tooltip/AGENTS.md +41 -0
  143. package/src/components/Tooltip/Tooltip.css +1 -0
  144. package/src/components/Tooltip/Tooltip.d.ts +12 -0
  145. package/src/components/Tooltip/Tooltip.scss +29 -0
  146. package/src/components/Tooltip/Tooltip2.esm.js +65 -0
  147. package/src/components/index.d.ts +17 -6
  148. package/src/styles/global/components/_button.scss +24 -21
  149. package/src/styles/global/components/_checkbox.scss +5 -4
  150. package/src/styles/global/components/_input.scss +1 -1
  151. package/src/styles/global/components/_radioButton.scss +5 -4
  152. package/src/styles/global/components/_typography.scss +6 -1
  153. package/src/styles/global/globalStyles.scss +9 -5
  154. package/src/styles/theme/components.esm.js +5 -6
  155. package/src/styles/utilities/_functions.scss +2 -2
  156. package/src/styles/utilities/_placeholders.scss +6 -0
  157. package/src/styles/utilities/layout.esm.js +3 -3
  158. package/src/utilities/types.d.ts +28 -3
  159. package/src/utilities/types.esm.js +11 -5
  160. package/src/utilities/validations.d.ts +5 -0
  161. package/src/utilities/validations.esm.js +19 -1
  162. package/src/components/Input/Checkbox.d.ts +0 -7
  163. package/src/components/Input/Checkbox.esm.js +0 -11
  164. package/src/components/Input/DatePicker.d.ts +0 -8
  165. package/src/components/Input/DatePicker.esm.js +0 -24
  166. package/src/components/Input/InputPassword.esm.js +0 -28
  167. package/src/components/Input/RadioButton.d.ts +0 -7
  168. package/src/components/Input/RadioButton.esm.js +0 -11
  169. package/src/components/Input/Textarea.esm.js +0 -24
  170. package/src/components/Modal/Modal.esm.js +0 -53
  171. package/src/components/Modal/Modal.module.css +0 -1
  172. package/src/components/Modal/Modal.module.esm.js +0 -16
  173. package/src/components/Modal/Modal.module.scss +0 -147
  174. package/src/styles/global/components/_reactCalendar.css +0 -1
  175. package/src/styles/global/components/_reactCalendar.scss +0 -237
  176. package/src/styles/global/components/_reactDatePicker.css +0 -1
  177. package/src/styles/global/components/_reactDatePicker.scss +0 -152
  178. package/src/styles/global/components/_reactPhone.css +0 -1
  179. package/src/styles/global/components/_reactPhone.scss +0 -265
  180. /package/src/components/{Progress.d.ts → Progress/Progress.d.ts} +0 -0
@@ -0,0 +1,13 @@
1
+ import { NoticeType } from '../../utilities/types';
2
+ export type NoticeProps = React.ComponentPropsWithoutRef<"div"> & {
3
+ type?: NoticeType;
4
+ icon?: React.ReactNode;
5
+ title?: string | React.ReactNode;
6
+ message?: string | React.ReactNode;
7
+ buttons?: React.ReactNode;
8
+ visible?: boolean;
9
+ dismissible?: boolean;
10
+ onDismiss?: (id?: string) => void;
11
+ id?: string;
12
+ };
13
+ export declare const Notice: React.FC<NoticeProps>;
@@ -0,0 +1,76 @@
1
+ @use "../../styles/utilities/_functions" as u;
2
+
3
+ @layer craftsman-component {
4
+ .notice {
5
+ transition: opacity 500ms ease-in-out;
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: #{u.width("gutter", 0.5)};
9
+ padding: #{u.width("gutter")};
10
+ border: 1px solid var(--gray400);
11
+ border-left-width: 3px;
12
+ background-color: var(--white);
13
+ border-radius: 4px;
14
+
15
+ &.info {
16
+ border-color: var(--blue500);
17
+ background-color: var(--blue50);
18
+ color: var(--blue600);
19
+ }
20
+
21
+ &.success {
22
+ border-color: var(--green500);
23
+ background-color: var(--green50);
24
+ border-color: var(--green500);
25
+ }
26
+
27
+ &.error {
28
+ border-color: var(--red500);
29
+ background-color: var(--red50);
30
+ color: var(--red600);
31
+ }
32
+
33
+ &.help {
34
+ border-color: var(--gray500);
35
+ background-color: var(--gray50);
36
+ }
37
+ button.text {
38
+ color: inherit;
39
+ }
40
+ }
41
+
42
+ .notice-contents {
43
+ display: flex;
44
+ flex-flow: row nowrap;
45
+ align-items: flex-start;
46
+ gap: #{u.width("gutter", 0.5)};
47
+ width: 100%;
48
+ }
49
+
50
+ .notice-icon {
51
+ display: flex;
52
+ flex: 0 0 auto;
53
+ font-size: 24px;
54
+ }
55
+
56
+ .notice-text {
57
+ flex-grow: 1;
58
+ margin-top: #{u.width("gutter", 0.25)};
59
+ span {
60
+ display: block;
61
+ }
62
+ }
63
+
64
+ .notice-dismiss {
65
+ flex: 0 0 auto;
66
+ padding: 0;
67
+ }
68
+
69
+ .notice-buttons {
70
+ width: 100%;
71
+ display: flex;
72
+ justify-content: flex-end;
73
+ gap: #{u.width("gutter", 0.5)};
74
+
75
+ }
76
+ }
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import { Button as e } from "../Button/Button.esm.js";
3
+ import { Text as t } from "../Text/Text2.esm.js";
4
+ import './Notice.css';/* empty css */
5
+ import n from "clsx";
6
+ import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
7
+ import { IoAlertCircleOutline as o, IoCheckmarkCircleOutline as s, IoCloseOutline as c, IoHelpCircleOutline as l, IoInformationCircleOutline as u } from "react-icons/io5";
8
+ //#region src/components/Notice/Notice.tsx
9
+ var d = {
10
+ info: /* @__PURE__ */ i(u, {}),
11
+ success: /* @__PURE__ */ i(s, {}),
12
+ error: /* @__PURE__ */ i(o, {}),
13
+ help: /* @__PURE__ */ i(l, {}),
14
+ none: /* @__PURE__ */ i(r, {})
15
+ }, f = (e, n) => typeof e == "string" ? /* @__PURE__ */ i(t, {
16
+ as: n,
17
+ children: e
18
+ }) : e, p = ({ type: t = "info", title: r, message: o, buttons: s, id: l, className: u, style: p, icon: m, children: h, dismissible: g, onDismiss: _, ...v }) => {
19
+ let y = () => {
20
+ _?.(l);
21
+ };
22
+ return /* @__PURE__ */ a("div", {
23
+ id: l,
24
+ className: n("notice", t, u),
25
+ style: p,
26
+ ...v,
27
+ children: [/* @__PURE__ */ a("div", {
28
+ className: "notice-contents",
29
+ children: [
30
+ t !== "none" && /* @__PURE__ */ i("div", {
31
+ className: "notice-icon",
32
+ children: m || d[t]
33
+ }),
34
+ /* @__PURE__ */ a("div", {
35
+ className: "notice-text",
36
+ children: [
37
+ r && f(r, "h5"),
38
+ o && f(o, "span"),
39
+ h
40
+ ]
41
+ }),
42
+ g && /* @__PURE__ */ i(e, {
43
+ variant: "text",
44
+ className: "notice-dismiss",
45
+ onClick: y,
46
+ children: /* @__PURE__ */ i(c, { size: 16 })
47
+ })
48
+ ]
49
+ }), s && /* @__PURE__ */ i("footer", {
50
+ className: "notice-buttons",
51
+ children: s
52
+ })]
53
+ });
54
+ };
55
+ //#endregion
56
+ export { p as Notice };
@@ -0,0 +1,38 @@
1
+ # Pagination — Agent Usage Notes
2
+
3
+ Import:
4
+
5
+ ```tsx
6
+ import { Pagination } from "@stamcat/craftsman/Pagination";
7
+ ```
8
+
9
+ Props:
10
+
11
+ - `total: number`
12
+ - `current: number`
13
+ - `showPages?: number` (default: `5`)
14
+ - `onChange: (e: React.MouseEvent<HTMLButtonElement>) => void`
15
+ - `className?: string`
16
+ - `style?: React.CSSProperties`
17
+
18
+ Behavior notes:
19
+
20
+ - Pagination is zero-based internally. Pass `current={0}` for the first page.
21
+ - `total` is the total number of pages, not the last page index.
22
+ - The component renders first/last buttons and jump-by-window buttons when needed.
23
+ - `showPages` controls both the visible window size and the jump step for `‹‹` / `››`.
24
+ - `onChange` receives the clicked button event. Read the next page from `event.currentTarget.value`.
25
+ - The active page button is disabled and marked with `aria-current="page"`.
26
+
27
+ Example:
28
+
29
+ ```tsx
30
+ const [current, setCurrent] = useState(0);
31
+
32
+ <Pagination
33
+ total={50}
34
+ current={current}
35
+ showPages={5}
36
+ onChange={(event) => setCurrent(parseInt(event.currentTarget.value, 10) || 0)}
37
+ />
38
+ ```
@@ -0,0 +1 @@
1
+ @layer craftsman-component{.pagination{align-items:center;gap:calc(var(--w-gutter) * .25);display:inline-flex}.pagination .active{color:var(--gray700);border:1px solid;border-radius:50%;justify-content:center;align-items:center;width:20px;height:20px;display:inline-flex}}
@@ -0,0 +1,10 @@
1
+ import { default as React } from 'react';
2
+ export type PaginationProps = {
3
+ total: number;
4
+ current: number;
5
+ showPages?: number;
6
+ onChange: (e: React.MouseEvent<HTMLButtonElement>) => void;
7
+ className?: string;
8
+ style?: React.CSSProperties;
9
+ };
10
+ export declare const Pagination: React.FC<PaginationProps>;
@@ -0,0 +1,22 @@
1
+
2
+ @use "../../styles/utilities/_functions" as u;
3
+
4
+ @layer craftsman-component {
5
+ .pagination {
6
+ display: inline-flex;
7
+ align-items: center;
8
+ gap: #{u.width("gutter", 0.25)};
9
+
10
+ .active {
11
+ color: #{u.color("gray700")};
12
+ border: 1px solid;
13
+ border-radius: 50%;
14
+ width: 20px;
15
+ height: 20px;
16
+ display: inline-flex;
17
+ align-items: center;
18
+ justify-content: center;
19
+
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,64 @@
1
+ "use client";
2
+ import './Pagination.css';/* empty css */
3
+ import e from "clsx";
4
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
5
+ import "react";
6
+ //#region src/components/Pagination/Pagination.tsx
7
+ var r = ({ total: r, current: i, onChange: a, className: o, style: s, showPages: c = 5 }) => {
8
+ function l(e, t) {
9
+ let n = Math.floor(c / 2), r = Math.max(0, e - n), i = Math.min(t - 1, r + c - 1);
10
+ r = Math.max(0, i - c + 1);
11
+ let a = [];
12
+ for (let e = r; e <= i; e++) a.push(e);
13
+ return a;
14
+ }
15
+ let u = l(i, r), d = Math.floor(i / c), f = d > 0, p = (d + 1) * c < r, m = (d - 1) * c, h = (d + 1) * c;
16
+ return /* @__PURE__ */ n("nav", {
17
+ className: e("pagination", o),
18
+ style: s,
19
+ "aria-label": "Pagination",
20
+ children: [
21
+ /* @__PURE__ */ t("button", {
22
+ className: "text",
23
+ value: 0,
24
+ onClick: a,
25
+ disabled: i === 0,
26
+ "aria-label": "First page",
27
+ children: "«"
28
+ }),
29
+ f && /* @__PURE__ */ t("button", {
30
+ className: "text",
31
+ value: m,
32
+ onClick: a,
33
+ "aria-label": `Back ${c} pages`,
34
+ children: "‹‹"
35
+ }),
36
+ u.map((n) => /* @__PURE__ */ t("button", {
37
+ value: n,
38
+ onClick: a,
39
+ disabled: n === i,
40
+ "aria-label": `Page ${n + 1}`,
41
+ "aria-current": n === i ? "page" : void 0,
42
+ className: e("text", n === i ? "active" : void 0),
43
+ children: n + 1
44
+ }, n)),
45
+ p && /* @__PURE__ */ t("button", {
46
+ className: "text",
47
+ value: h,
48
+ onClick: a,
49
+ "aria-label": `Forward ${c} pages`,
50
+ children: "››"
51
+ }),
52
+ /* @__PURE__ */ t("button", {
53
+ className: "text",
54
+ value: r - 1,
55
+ onClick: a,
56
+ disabled: i === r - 1,
57
+ "aria-label": "Last page",
58
+ children: "»"
59
+ })
60
+ ]
61
+ });
62
+ };
63
+ //#endregion
64
+ export { r as Pagination };
@@ -0,0 +1,44 @@
1
+ # RadioButton — Agent Usage Notes
2
+
3
+ Import:
4
+
5
+ ```tsx
6
+ import { RadioButton } from "@stamcat/craftsman/RadioButton";
7
+ ```
8
+
9
+ Props:
10
+
11
+ - Extends `Input` props.
12
+ - `type?: "radio"` (default: `"radio"`)
13
+ - `labelPosition?: "left" | "right"` (default: `"right"`)
14
+ - `size?: number` (default visual scale is `1`, clamped to `[0.1, 10]`)
15
+
16
+ Behavior notes:
17
+
18
+ - `RadioButton` is a thin wrapper around `Input` with radio-specific guardrails.
19
+ - Group behavior is native HTML radio behavior: use a shared `name` across options.
20
+ - Controlled and uncontrolled patterns are both supported (`checked` + `onChange`, or `defaultChecked`).
21
+ - When `size` is provided, RadioButton sets a single `--radio-size` CSS variable inline; the radio circle and dot scale via SCSS `calc()` from that variable (same pattern as `Button`'s `--btn-size` and `Toggle`'s `--toggle-width`).
22
+
23
+ Example:
24
+
25
+ ```tsx
26
+ <>
27
+ <RadioButton
28
+ id="captain-kirk"
29
+ name="favorite-captain"
30
+ value="Kirk"
31
+ label="James T. Kirk"
32
+ checked={selected === "Kirk"}
33
+ onChange={(event) => setSelected(event.currentTarget.value)}
34
+ />
35
+ <RadioButton
36
+ id="captain-picard"
37
+ name="favorite-captain"
38
+ value="Picard"
39
+ label="Jean-Luc Picard"
40
+ checked={selected === "Picard"}
41
+ onChange={(event) => setSelected(event.currentTarget.value)}
42
+ />
43
+ </>
44
+ ```
@@ -0,0 +1,9 @@
1
+ import { RadioLabelPosition } from '../../styles';
2
+ import { InputProps } from '../Input/Input';
3
+ type RadioButtonProps = InputProps & {
4
+ type?: "radio";
5
+ labelPosition?: RadioLabelPosition;
6
+ size?: number;
7
+ };
8
+ export declare const RadioButton: React.FC<RadioButtonProps>;
9
+ export {};
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { Input as e } from "../Input/Input2.esm.js";
3
+ import { jsx as t } from "react/jsx-runtime";
4
+ //#region src/components/RadioButton/RadioButton.tsx
5
+ var n = ({ type: n = "radio", labelPosition: r = "right", size: i, style: a, ...o }) => {
6
+ let s = typeof i == "number" ? Math.min(10, Math.max(.1, i)) : void 0;
7
+ return /* @__PURE__ */ t(e, {
8
+ type: n,
9
+ labelPosition: r,
10
+ style: {
11
+ ...s ? { "--radio-size": s } : void 0,
12
+ ...a
13
+ },
14
+ ...o
15
+ });
16
+ };
17
+ //#endregion
18
+ export { n as RadioButton };
@@ -0,0 +1,36 @@
1
+ # Select — Agent Usage Notes
2
+
3
+ Import:
4
+
5
+ ```tsx
6
+ import { Select } from "@stamcat/craftsman/Select";
7
+ ```
8
+
9
+ Props:
10
+
11
+ - Inherits all native `<select>` props.
12
+ - `label?: string | ReactNode`
13
+ - `labelPosition?: "top" | "left" | "bottom" | "right" | "inside" | "hidden"` (default: `"top"`)
14
+ - `error?: string | boolean | ReactNode`
15
+ - `required?: boolean`
16
+ - `options?: Array<{ label: string; value: string }>`
17
+
18
+ Behavior notes:
19
+
20
+ - Built on the native `<select>` element via `InputWrapper`.
21
+ - Pass options as a plain array — do not render `<option>` children manually.
22
+ - `id` is auto-generated via `useId` if not provided.
23
+
24
+ Example:
25
+
26
+ ```tsx
27
+ <Select
28
+ label="Favorite Fruit"
29
+ required
30
+ options={[
31
+ { value: "", label: "Select one..." },
32
+ { value: "apple", label: "Apple" },
33
+ { value: "banana", label: "Banana" },
34
+ ]}
35
+ />
36
+ ```
@@ -0,0 +1,45 @@
1
+ # SortableList — Agent Usage Notes
2
+
3
+ Import:
4
+
5
+ ```tsx
6
+ import { SortableList } from "@stamcat/craftsman/SortableList";
7
+ ```
8
+
9
+ Props:
10
+
11
+ - `items: T[]`
12
+ - `getKey: (item: T, index: number) => string`
13
+ - `renderItem: (args: SortableListRenderArgs<T>) => React.ReactNode`
14
+ - `onReorder: (items: T[]) => void`
15
+ - `disabled?: boolean`
16
+ - `className?: string`
17
+ - `style?: React.CSSProperties`
18
+
19
+ Behavior notes:
20
+
21
+ - Built on `@atlaskit/pragmatic-drag-and-drop`. The list only owns drag/drop wiring and reordering — all item markup comes from `renderItem`.
22
+ - `renderItem` receives `{ item, index, isDragging, dropEdge, dragHandleRef }`.
23
+ - By default the whole rendered item is the drag source.
24
+ - To restrict dragging to a handle, attach `dragHandleRef` to the handle element's `ref`.
25
+ - `dropEdge` is `"top" | "bottom" | null` while another item is dragged over this one — use it to render a drop indicator, or rely on the built-in `.drop-top` / `.drop-bottom` styles.
26
+ - `onReorder` is called with the full reordered array on drop; the component does not mutate `items` itself — update your own state in the callback.
27
+ - Set `disabled` to suspend all drag/drop wiring (for example while a related request is in flight).
28
+
29
+ Example:
30
+
31
+ ```tsx
32
+ const [items, setItems] = useState(["Alpha", "Beta", "Gamma"]);
33
+
34
+ <SortableList
35
+ items={items}
36
+ getKey={(item) => item}
37
+ onReorder={setItems}
38
+ renderItem={({ item, isDragging, dropEdge, dragHandleRef }) => (
39
+ <div className={isDragging ? "dragging" : undefined} data-drop-edge={dropEdge ?? undefined}>
40
+ <span ref={dragHandleRef}>⠿</span>
41
+ {item}
42
+ </div>
43
+ )}
44
+ />
45
+ ```
@@ -0,0 +1,10 @@
1
+ import { SortableListRenderArgs } from './SortableList';
2
+ export type DropEdge = "top" | "bottom";
3
+ export declare function SortableListItem<T>({ item, index, getKey, renderItem, disabled, listId, }: {
4
+ item: T;
5
+ index: number;
6
+ getKey: (item: T, index: number) => string;
7
+ renderItem: (args: SortableListRenderArgs<T>) => React.ReactNode;
8
+ disabled?: boolean;
9
+ listId: string;
10
+ }): import("react").JSX.Element;
@@ -0,0 +1,67 @@
1
+ "use client";
2
+ import { combine as e } from "../../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/combine.esm.js";
3
+ import { draggable as t, dropTargetForElements as n } from "../../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/adapter/element-adapter.esm.js";
4
+ import { isItemData as r } from "./utilities.esm.js";
5
+ import i from "clsx";
6
+ import { jsx as a } from "react/jsx-runtime";
7
+ import { useEffect as o, useLayoutEffect as s, useRef as c, useState as l } from "react";
8
+ //#region src/components/SortableList/ListItem.tsx
9
+ function u({ item: u, index: d, getKey: f, renderItem: p, disabled: m, listId: h }) {
10
+ let [g, _] = l(null), [v, y] = l(null), [b, x] = l(!1), [S, C] = l(null), w = c(null), T = c(null), E = f(u, d);
11
+ return s(() => {
12
+ w.current = g;
13
+ let e = w.current;
14
+ if (!e) return;
15
+ let t = T.current, n = e.getBoundingClientRect();
16
+ T.current = n;
17
+ let r = t ? t.top - n.top : 0;
18
+ !r || window.matchMedia("(prefers-reduced-motion: reduce)").matches || (e.style.transition = "none", e.style.transform = `translateY(${r}px)`, requestAnimationFrame(() => {
19
+ e.style.transition = "", e.style.transform = "";
20
+ }));
21
+ }, [g, d]), o(() => {
22
+ if (!g || m) return;
23
+ let i = {
24
+ key: E,
25
+ index: d,
26
+ listId: h,
27
+ item: u
28
+ };
29
+ return e(t({
30
+ element: g,
31
+ dragHandle: v ?? void 0,
32
+ getInitialData: () => i,
33
+ onDragStart: () => x(!0),
34
+ onDrop: () => x(!1)
35
+ }), n({
36
+ element: g,
37
+ getData: () => i,
38
+ canDrop: ({ source: e }) => r(e.data) && e.data.key !== E,
39
+ onDrag: ({ location: e }) => {
40
+ let t = g.getBoundingClientRect(), n = e.current.input.clientY > t.top + t.height / 2;
41
+ C(n ? "bottom" : "top");
42
+ },
43
+ onDragLeave: () => C(null),
44
+ onDrop: () => C(null)
45
+ }));
46
+ }, [
47
+ g,
48
+ v,
49
+ E,
50
+ d,
51
+ m,
52
+ h,
53
+ u
54
+ ]), /* @__PURE__ */ a("li", {
55
+ ref: _,
56
+ className: i("sortable-list-item", b && "dragging", S && `drop-${S}`),
57
+ children: p({
58
+ item: u,
59
+ index: d,
60
+ isDragging: b,
61
+ dropEdge: S,
62
+ dragHandleRef: y
63
+ })
64
+ }, E);
65
+ }
66
+ //#endregion
67
+ export { u as SortableListItem };
@@ -0,0 +1 @@
1
+ @layer craftsman-component{.sortable-list{gap:calc(var(--w-gutter) * .25);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.sortable-list-item{cursor:grab;transition:transform .2s,opacity .15s;position:relative}.sortable-list-item.dragging{opacity:.4}.sortable-list-item.drop-top:before,.sortable-list-item.drop-bottom:after{content:"";background-color:var(--blue500);border-radius:1px;height:2px;position:absolute;left:0;right:0}.sortable-list-item.drop-top:before{top:-1px}.sortable-list-item.drop-bottom:after{bottom:-1px}}
@@ -0,0 +1,23 @@
1
+ import { default as React } from 'react';
2
+ import { DropEdge } from './ListItem';
3
+ export type SortableListItemState = {
4
+ isDragging: boolean;
5
+ dropEdge: DropEdge | null;
6
+ };
7
+ export type SortableListRenderArgs<T> = SortableListItemState & {
8
+ dragHandleRef: (element: HTMLElement | null) => void;
9
+ item: T;
10
+ index: number;
11
+ };
12
+ export type SortableListProps<T> = {
13
+ items: T[];
14
+ getKey: (item: T, index: number) => string;
15
+ renderItem: (args: SortableListRenderArgs<T>) => React.ReactNode;
16
+ onReorder: (items: T[]) => void;
17
+ disabled?: boolean;
18
+ className?: string;
19
+ style?: React.CSSProperties;
20
+ listId?: string;
21
+ onReceive?: (item: T, atIndex: number) => void;
22
+ };
23
+ export declare const SortableList: <T>({ items, getKey, renderItem, onReorder, disabled, className, style, listId, onReceive }: SortableListProps<T>) => React.JSX.Element;
@@ -0,0 +1,41 @@
1
+ @use "../../styles/utilities/_functions" as u;
2
+
3
+ @layer craftsman-component {
4
+ .sortable-list {
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: #{u.width("gutter", 0.25)};
8
+ margin: 0;
9
+ padding: 0;
10
+ list-style: none;
11
+ }
12
+
13
+ .sortable-list-item {
14
+ position: relative;
15
+ cursor: grab;
16
+ transition: transform 200ms ease, opacity 150ms ease;
17
+
18
+ &.dragging {
19
+ opacity: 0.4;
20
+ }
21
+
22
+ &.drop-top::before,
23
+ &.drop-bottom::after {
24
+ content: "";
25
+ position: absolute;
26
+ left: 0;
27
+ right: 0;
28
+ height: 2px;
29
+ border-radius: 1px;
30
+ background-color: #{u.color("blue500")};
31
+ }
32
+
33
+ &.drop-top::before {
34
+ top: -1px;
35
+ }
36
+
37
+ &.drop-bottom::after {
38
+ bottom: -1px;
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import { monitorForElements as e } from "../../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/adapter/element-adapter.esm.js";
3
+ import { reorder as t } from "../../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/reorder.esm.js";
4
+ import './SortableList.css';/* empty css */
5
+ import { isItemData as n } from "./utilities.esm.js";
6
+ import { SortableListItem as r } from "./ListItem.esm.js";
7
+ import i from "clsx";
8
+ import { jsx as a } from "react/jsx-runtime";
9
+ import { useEffect as o, useId as s } from "react";
10
+ //#region src/components/SortableList/SortableList.tsx
11
+ var c = ({ items: c, getKey: l, renderItem: u, onReorder: d, disabled: f, className: p, style: m, listId: h, onReceive: g }) => {
12
+ let _ = s(), v = h ?? _, y = (e, n) => {
13
+ let r = c.findIndex((t, n) => l(t, n) === e), i = c.findIndex((e, t) => l(e, t) === n);
14
+ r === -1 || i === -1 || r === i || d(t({
15
+ list: c,
16
+ startIndex: r,
17
+ finishIndex: i
18
+ }));
19
+ }, b = (e) => {
20
+ let t = c.findIndex((t, n) => l(t, n) === e);
21
+ t !== -1 && d(c.filter((e, n) => n !== t));
22
+ }, x = (e, t) => {
23
+ let n = c.findIndex((e, n) => l(e, n) === t);
24
+ g?.(e, n === -1 ? c.length : n);
25
+ };
26
+ return o(() => {
27
+ if (!f) return e({ onDrop: ({ source: e, location: t }) => {
28
+ let r = t.current.dropTargets[0];
29
+ if (!r || !n(e.data) || !n(r.data)) return;
30
+ let i = e.data.listId, a = r.data.listId, o = i === v, s = a === v;
31
+ o && s ? y(e.data.key, r.data.key) : o ? b(e.data.key) : s && g && x(e.data.item, r.data.key);
32
+ } });
33
+ }, [
34
+ c,
35
+ l,
36
+ d,
37
+ f,
38
+ v,
39
+ g
40
+ ]), /* @__PURE__ */ a("ul", {
41
+ className: i("sortable-list", p),
42
+ style: m,
43
+ children: c.map((e, t) => /* @__PURE__ */ a(r, {
44
+ item: e,
45
+ index: t,
46
+ getKey: l,
47
+ renderItem: u,
48
+ disabled: f,
49
+ listId: v
50
+ }, l(e, t)))
51
+ });
52
+ };
53
+ //#endregion
54
+ export { c as SortableList };
@@ -0,0 +1,7 @@
1
+ export type ItemData = {
2
+ key: string;
3
+ index: number;
4
+ listId: string;
5
+ item: unknown;
6
+ };
7
+ export declare const isItemData: (data: Record<string | symbol, unknown>) => data is ItemData;
@@ -0,0 +1,4 @@
1
+ //#region src/components/SortableList/utilities.ts
2
+ var e = (e) => typeof e.key == "string" && typeof e.index == "number" && typeof e.listId == "string";
3
+ //#endregion
4
+ export { e as isItemData };