@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.
- package/AGENTS.md +21 -403
- package/Components.esm.js +62 -11
- package/README.md +63 -12
- package/Styles.esm.js +7 -7
- package/Utilities.esm.js +2 -2
- package/_virtual/_rolldown/runtime.esm.js +18 -6
- package/package.json +51 -3
- package/src/components/Button/AGENTS.md +65 -0
- package/src/components/Button/Button.d.ts +1 -1
- package/src/components/Button/Button.esm.js +11 -17
- package/src/components/Carousel/AGENTS.md +41 -0
- package/src/components/Carousel/Carousel.css +1 -0
- package/src/components/Carousel/Carousel.d.ts +11 -0
- package/src/components/Carousel/Carousel.scss +34 -0
- package/src/components/Carousel/Carousel2.esm.js +75 -0
- package/src/components/Checkbox/AGENTS.md +34 -0
- package/src/components/Checkbox/Checkbox.d.ts +8 -0
- package/src/components/Checkbox/Checkbox.esm.js +18 -0
- package/src/components/DatePicker/AGENTS.md +36 -0
- package/src/components/DatePicker/DatePicker.css +1 -0
- package/src/components/DatePicker/DatePicker.d.ts +8 -0
- package/src/components/DatePicker/DatePicker.scss +61 -0
- package/src/components/DatePicker/DatePicker2.esm.js +29 -0
- package/src/components/DatePicker/ReactCalendar.css +1 -0
- package/src/components/DatePicker/ReactCalendar.scss +158 -0
- package/src/components/DatePicker/_DatePicker.scss +73 -0
- package/src/components/DateRangePicker/AGENTS.md +38 -0
- package/src/components/DateRangePicker/DateRangePicker.css +1 -0
- package/src/components/DateRangePicker/DateRangePicker.d.ts +8 -0
- package/src/components/DateRangePicker/DateRangePicker.scss +62 -0
- package/src/components/DateRangePicker/DateRangePicker2.esm.js +29 -0
- package/src/components/DateTimePicker/AGENTS.md +41 -0
- package/src/components/DateTimePicker/DateTimePicker.css +1 -0
- package/src/components/DateTimePicker/DateTimePicker.d.ts +13 -0
- package/src/components/DateTimePicker/DateTimePicker.scss +86 -0
- package/src/components/DateTimePicker/DateTimePicker2.esm.js +82 -0
- package/src/components/Icons/IconAmazonPay.d.ts +2 -0
- package/src/components/Icons/IconAmazonPay.esm.js +76 -0
- package/src/components/Icons/IconAmex.d.ts +2 -0
- package/src/components/Icons/IconAmex.esm.js +87 -0
- package/src/components/Icons/IconApplePay.d.ts +2 -0
- package/src/components/Icons/IconApplePay.esm.js +26 -0
- package/src/components/Icons/IconDiscover.d.ts +2 -0
- package/src/components/Icons/IconDiscover.esm.js +129 -0
- package/src/components/Icons/IconGooglePay.d.ts +2 -0
- package/src/components/Icons/IconGooglePay.esm.js +64 -0
- package/src/components/Icons/IconMaestro.d.ts +2 -0
- package/src/components/Icons/IconMaestro.esm.js +38 -0
- package/src/components/Icons/IconMastercard.d.ts +2 -0
- package/src/components/Icons/IconMastercard.esm.js +27 -0
- package/src/components/Icons/IconPayPal.d.ts +2 -0
- package/src/components/Icons/IconPayPal.esm.js +52 -0
- package/src/components/Icons/IconSepa.d.ts +2 -0
- package/src/components/Icons/IconSepa.esm.js +272 -0
- package/src/components/Icons/IconShopPay.d.ts +2 -0
- package/src/components/Icons/IconShopPay.esm.js +35 -0
- package/src/components/Icons/IconSquare.d.ts +2 -0
- package/src/components/Icons/IconSquare.esm.js +11 -0
- package/src/components/Icons/IconStripe.d.ts +2 -0
- package/src/components/Icons/IconStripe.esm.js +57 -0
- package/src/components/Icons/IconUnionPay.d.ts +2 -0
- package/src/components/Icons/IconUnionPay.esm.js +28 -0
- package/src/components/Icons/IconVenmo.d.ts +2 -0
- package/src/components/Icons/IconVenmo.esm.js +21 -0
- package/src/components/Icons/IconVisa.d.ts +2 -0
- package/src/components/Icons/IconVisa.esm.js +14 -0
- package/src/components/Icons/index.d.ts +15 -0
- package/src/components/Icons/index.esm.js +16 -0
- package/src/components/Icons/types.d.ts +4 -0
- package/src/components/Input/AGENTS.md +30 -0
- package/src/components/Input/Input.css +1 -1
- package/src/components/Input/Input.scss +108 -95
- package/src/components/Input/Input2.esm.js +27 -18
- package/src/components/Input/InputWrapper.d.ts +1 -0
- package/src/components/InputNumber/AGENTS.md +37 -0
- package/src/components/InputNumber/InputNumber.css +1 -0
- package/src/components/InputNumber/InputNumber.d.ts +10 -0
- package/src/components/InputNumber/InputNumber.scss +29 -0
- package/src/components/InputNumber/InputNumber2.esm.js +36 -0
- package/src/components/InputPassword/AGENTS.md +29 -0
- package/src/components/{Input → InputPassword}/InputPassword.d.ts +1 -1
- package/src/components/InputPassword/InputPassword.esm.js +30 -0
- package/src/components/InputPhone/AGENTS.md +35 -0
- package/src/components/InputPhone/InputPhone.css +1 -0
- package/src/components/{Input → InputPhone}/InputPhone.d.ts +1 -1
- package/src/components/InputPhone/InputPhone.scss +266 -0
- package/src/components/{Input/InputPhone.esm.js → InputPhone/InputPhone2.esm.js} +4 -4
- package/src/components/Loader/AGENTS.md +31 -0
- package/src/components/Loader/Loader.esm.js +1 -1
- package/src/components/Loader/types.d.ts +1 -1
- package/src/components/Modal/AGENTS.md +47 -0
- package/src/components/Modal/Modal.css +1 -0
- package/src/components/Modal/Modal.scss +150 -0
- package/src/components/Modal/Modal2.esm.js +53 -0
- package/src/components/Notice/AGENTS.md +42 -0
- package/src/components/Notice/Notice.css +1 -0
- package/src/components/Notice/Notice.d.ts +13 -0
- package/src/components/Notice/Notice.scss +76 -0
- package/src/components/Notice/Notice2.esm.js +56 -0
- package/src/components/Pagination/AGENTS.md +38 -0
- package/src/components/Pagination/Pagination.css +1 -0
- package/src/components/Pagination/Pagination.d.ts +10 -0
- package/src/components/Pagination/Pagination.scss +22 -0
- package/src/components/Pagination/Pagination2.esm.js +64 -0
- package/src/components/RadioButton/AGENTS.md +44 -0
- package/src/components/RadioButton/RadioButton.d.ts +9 -0
- package/src/components/RadioButton/RadioButton.esm.js +18 -0
- package/src/components/Select/AGENTS.md +36 -0
- package/src/components/SortableList/AGENTS.md +45 -0
- package/src/components/SortableList/ListItem.d.ts +10 -0
- package/src/components/SortableList/ListItem.esm.js +67 -0
- package/src/components/SortableList/SortableList.css +1 -0
- package/src/components/SortableList/SortableList.d.ts +23 -0
- package/src/components/SortableList/SortableList.scss +41 -0
- package/src/components/SortableList/SortableList2.esm.js +54 -0
- package/src/components/SortableList/utilities.d.ts +7 -0
- package/src/components/SortableList/utilities.esm.js +4 -0
- package/src/components/Text/AGENTS.md +32 -0
- package/src/components/Text/Text.css +1 -1
- package/src/components/Text/Text.scss +2 -2
- package/src/components/Textarea/AGENTS.md +32 -0
- package/src/components/{Input → Textarea}/Textarea.d.ts +1 -1
- package/src/components/Textarea/Textarea.esm.js +23 -0
- package/src/components/TimePicker/AGENTS.md +42 -0
- package/src/components/TimePicker/TimePicker.css +1 -0
- package/src/components/TimePicker/TimePicker.d.ts +13 -0
- package/src/components/TimePicker/TimePicker.scss +226 -0
- package/src/components/TimePicker/TimePicker2.esm.js +98 -0
- package/src/components/TimePicker/TimePickerDisplay.d.ts +16 -0
- package/src/components/TimePicker/TimePickerDisplay.esm.js +54 -0
- package/src/components/TimePicker/TimePickerWheel.d.ts +13 -0
- package/src/components/TimePicker/TimePickerWheel.esm.js +61 -0
- package/src/components/TimePicker/constants.d.ts +7 -0
- package/src/components/TimePicker/constants.esm.js +3 -0
- package/src/components/TimePicker/utilities.d.ts +15 -0
- package/src/components/TimePicker/utilities.esm.js +20 -0
- package/src/components/Toggle/AGENTS.md +33 -0
- package/src/components/Toggle/Toggle.css +1 -0
- package/src/components/Toggle/Toggle.d.ts +5 -0
- package/src/components/Toggle/Toggle.scss +64 -0
- package/src/components/Toggle/Toggle2.esm.js +19 -0
- package/src/components/Tooltip/AGENTS.md +41 -0
- package/src/components/Tooltip/Tooltip.css +1 -0
- package/src/components/Tooltip/Tooltip.d.ts +12 -0
- package/src/components/Tooltip/Tooltip.scss +29 -0
- package/src/components/Tooltip/Tooltip2.esm.js +65 -0
- package/src/components/index.d.ts +17 -6
- package/src/styles/global/components/_button.scss +24 -21
- package/src/styles/global/components/_checkbox.scss +5 -4
- package/src/styles/global/components/_input.scss +1 -1
- package/src/styles/global/components/_radioButton.scss +5 -4
- package/src/styles/global/components/_typography.scss +6 -1
- package/src/styles/global/globalStyles.scss +9 -5
- package/src/styles/theme/components.esm.js +5 -6
- package/src/styles/utilities/_functions.scss +2 -2
- package/src/styles/utilities/_placeholders.scss +6 -0
- package/src/styles/utilities/layout.esm.js +3 -3
- package/src/utilities/types.d.ts +28 -3
- package/src/utilities/types.esm.js +11 -5
- package/src/utilities/validations.d.ts +5 -0
- package/src/utilities/validations.esm.js +19 -1
- package/src/components/Input/Checkbox.d.ts +0 -7
- package/src/components/Input/Checkbox.esm.js +0 -11
- package/src/components/Input/DatePicker.d.ts +0 -8
- package/src/components/Input/DatePicker.esm.js +0 -24
- package/src/components/Input/InputPassword.esm.js +0 -28
- package/src/components/Input/RadioButton.d.ts +0 -7
- package/src/components/Input/RadioButton.esm.js +0 -11
- package/src/components/Input/Textarea.esm.js +0 -24
- package/src/components/Modal/Modal.esm.js +0 -53
- package/src/components/Modal/Modal.module.css +0 -1
- package/src/components/Modal/Modal.module.esm.js +0 -16
- package/src/components/Modal/Modal.module.scss +0 -147
- package/src/styles/global/components/_reactCalendar.css +0 -1
- package/src/styles/global/components/_reactCalendar.scss +0 -237
- package/src/styles/global/components/_reactDatePicker.css +0 -1
- package/src/styles/global/components/_reactDatePicker.scss +0 -152
- package/src/styles/global/components/_reactPhone.css +0 -1
- package/src/styles/global/components/_reactPhone.scss +0 -265
- /package/src/components/{Progress.d.ts → Progress/Progress.d.ts} +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EmblaCarouselType } from 'embla-carousel';
|
|
2
|
+
export declare const parseTimeString: (val: unknown) => [number, number];
|
|
3
|
+
export declare const padTime: (n: number) => string;
|
|
4
|
+
export declare const toDisplayHour: (hours: number, is12h: boolean) => number;
|
|
5
|
+
export declare const to24Hour: (display: number, isPM: boolean, is12h: boolean) => number;
|
|
6
|
+
export declare const resolveLocale: (locale?: Intl.LocalesArgument) => string;
|
|
7
|
+
export declare const resolveTimeFormat: (format: 24 | 12 | undefined, is24h: boolean) => 24 | 12;
|
|
8
|
+
export declare const isInView: (wheelLocation: number, slidePosition: number) => boolean;
|
|
9
|
+
export declare const setSlideStyles: (emblaApi: EmblaCarouselType, index: number, loop: boolean, slideCount: number, totalRadius: number) => void;
|
|
10
|
+
export declare const setContainerStyles: (emblaApi: EmblaCarouselType, wheelRotation: number) => void;
|
|
11
|
+
export declare const inactivateEmblaTransform: (emblaApi: EmblaCarouselType) => void;
|
|
12
|
+
export declare const snapOnPointerUp: (emblaApi: EmblaCarouselType) => void;
|
|
13
|
+
export declare const resolveHasValue: (value: React.ComponentProps<"input">["value"], internalHours: number | null) => boolean;
|
|
14
|
+
export declare const resolveTime: (value: unknown, h: number | null, m: number | null) => [number, number];
|
|
15
|
+
export declare const toDisplayInputValue: (hasVal: boolean, val: string | number) => string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { WHEEL_RADIUS as e } from "./constants.esm.js";
|
|
2
|
+
//#region src/components/TimePicker/utilities.ts
|
|
3
|
+
var t = (e) => {
|
|
4
|
+
if (typeof e != "string" || !e.includes(":")) return [0, 0];
|
|
5
|
+
let [t, n] = e.split(":").map(Number);
|
|
6
|
+
return [isNaN(t) ? 0 : t, isNaN(n) ? 0 : n];
|
|
7
|
+
}, n = (e) => String(e).padStart(2, "0"), r = (e, t, n) => n ? e === 12 ? t ? 12 : 0 : t ? e + 12 : e : e, i = (e) => e ? String(Array.isArray(e) ? e[0] : e) : typeof navigator < "u" ? navigator.language : "en-US", a = (e, t) => e ?? (t ? 24 : 12), o = (e, t) => Math.abs(e - t) < 80, s = (t, n, r, i, a) => {
|
|
8
|
+
let s = t.slideNodes()[n], c = t.scrollProgress() * a, l = t.scrollSnapList()[n] * a, u = l + a, d = l - a, f = !1, p = n * -20;
|
|
9
|
+
o(c, l) && (f = !0), r && o(c, d) && (f = !0, p = -360 + (i - n) * 20), r && o(c, u) && (f = !0, p = -(a % 360) - n * 20), f ? (s.style.opacity = "1", s.style.transform = `translateY(-${n * 100}%) rotateX(${p}deg) translateZ(${e}px)`) : (s.style.opacity = "0", s.style.transform = "none");
|
|
10
|
+
}, c = (t, n) => {
|
|
11
|
+
t.containerNode().style.transform = `translateZ(${e}px) rotateX(${n}deg)`;
|
|
12
|
+
}, l = (e) => {
|
|
13
|
+
let { translate: t } = e.internalEngine();
|
|
14
|
+
t.clear(), t.toggleActive(!1);
|
|
15
|
+
}, u = (e) => {
|
|
16
|
+
let { scrollTo: t, target: n, location: r } = e.internalEngine(), i = n.get() - r.get(), a = Math.abs(i) < 32 / 2.5 ? 10 : .1;
|
|
17
|
+
t.distance(i * a, !0);
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { l as inactivateEmblaTransform, o as isInView, n as padTime, t as parseTimeString, i as resolveLocale, a as resolveTimeFormat, c as setContainerStyles, s as setSlideStyles, u as snapOnPointerUp, r as to24Hour };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Toggle — Agent Usage Notes
|
|
2
|
+
|
|
3
|
+
Import:
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Toggle } from "@stamcat/craftsman/Toggle";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Props:
|
|
10
|
+
|
|
11
|
+
- Extends `Input` props, excluding `type`, `preAdornment`, and `endAdornment` (all internally managed).
|
|
12
|
+
- `width?: number` — pixel width of the switch track (default: `40`). Track height, thumb size, and thumb travel all derive from this via `calc()`.
|
|
13
|
+
- `label?: string | ReactNode`, `labelPosition?: "top" | "left" | "bottom" | "right" | "inside" | "hidden"` (default: `"right"`), `error?`, `required?` — same as `Input`.
|
|
14
|
+
|
|
15
|
+
Behavior notes:
|
|
16
|
+
|
|
17
|
+
- `Toggle` is `<Input type="checkbox">` under the hood — it is a real, keyboard-accessible checkbox styled as a switch, not a custom widget.
|
|
18
|
+
- `width` sets a single `--toggle-width` CSS variable inline; the track, thumb, and checked-state translation are all `calc()`-derived from it in `Toggle.scss` (the same sizing pattern used by `Button`'s `--btn-size`, `Checkbox`'s `--checkbox-size`, and `RadioButton`'s `--radio-size`).
|
|
19
|
+
- The underlying checkbox input is stretched invisibly over the full switch (`opacity: 0`) so it stays the real click/keyboard target; the visual slider is rendered via `endAdornment` with `pointer-events: none`.
|
|
20
|
+
- Controlled and uncontrolled patterns are both supported (`checked` + `onChange`, or `defaultChecked`).
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
const [enabled, setEnabled] = useState(false);
|
|
26
|
+
|
|
27
|
+
<Toggle
|
|
28
|
+
label="Enable notifications"
|
|
29
|
+
width={48}
|
|
30
|
+
checked={enabled}
|
|
31
|
+
onChange={(event) => setEnabled(event.currentTarget.checked)}
|
|
32
|
+
/>
|
|
33
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer craftsman-component{.input-wrapper.toggle>label{align-items:center;gap:calc(var(--w-gutter) * .5);display:inline-flex}.input-wrapper.toggle .input-field{width:var(--toggle-width,60px);height:calc(var(--toggle-width,60px) * .56);position:relative}.input-wrapper.toggle .input.checkbox{opacity:0;cursor:pointer;z-index:1;width:100%;height:100%;margin:0;position:absolute;inset:0}.input-wrapper.toggle .input-end-adornment{position:absolute;inset:0;transform:none}.input-wrapper.toggle .toggle-slider{pointer-events:none;background-color:var(--gray400);border-radius:calc(var(--toggle-width,60px) * .56);transition:background-color .2s;position:absolute;inset:0}.input-wrapper.toggle .toggle-slider:before{content:"";left:calc(var(--toggle-width,60px) * .065);bottom:calc(var(--toggle-width,60px) * .065);height:calc(var(--toggle-width,60px) * .43);width:calc(var(--toggle-width,60px) * .43);background-color:var(--white);border-radius:50%;transition:transform .2s;position:absolute}.input-wrapper.toggle .input.checkbox:checked+.input-end-adornment .toggle-slider{background-color:var(--blue500)}.input-wrapper.toggle .input.checkbox:checked+.input-end-adornment .toggle-slider:before{transform:translateX(calc(var(--toggle-width,60px) * .43))}}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
@use "../../styles/utilities/_functions" as u;
|
|
2
|
+
|
|
3
|
+
@layer craftsman-component {
|
|
4
|
+
.input-wrapper.toggle {
|
|
5
|
+
> label {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
gap: #{u.width("gutter", 0.5)};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.input-field {
|
|
12
|
+
position: relative;
|
|
13
|
+
width: var(--toggle-width, 60px);
|
|
14
|
+
height: calc(var(--toggle-width, 60px) * 0.56);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.input.checkbox {
|
|
18
|
+
position: absolute;
|
|
19
|
+
inset: 0;
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
margin: 0;
|
|
23
|
+
opacity: 0;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
z-index: 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.input-end-adornment {
|
|
29
|
+
position: absolute;
|
|
30
|
+
inset: 0;
|
|
31
|
+
top: 0;
|
|
32
|
+
transform: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.toggle-slider {
|
|
36
|
+
position: absolute;
|
|
37
|
+
inset: 0;
|
|
38
|
+
pointer-events: none;
|
|
39
|
+
background-color: var(--gray400);
|
|
40
|
+
border-radius: calc(var(--toggle-width, 60px) * 0.56);
|
|
41
|
+
transition: background-color 0.2s ease;
|
|
42
|
+
|
|
43
|
+
&::before {
|
|
44
|
+
position: absolute;
|
|
45
|
+
content: "";
|
|
46
|
+
left: calc(var(--toggle-width, 60px) * 0.065);
|
|
47
|
+
bottom: calc(var(--toggle-width, 60px) * 0.065);
|
|
48
|
+
height: calc(var(--toggle-width, 60px) * 0.43);
|
|
49
|
+
width: calc(var(--toggle-width, 60px) * 0.43);
|
|
50
|
+
border-radius: 50%;
|
|
51
|
+
background-color: var(--white);
|
|
52
|
+
transition: transform 0.2s ease;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.input.checkbox:checked + .input-end-adornment .toggle-slider {
|
|
57
|
+
background-color: var(--blue500);
|
|
58
|
+
|
|
59
|
+
&::before {
|
|
60
|
+
transform: translateX(calc(var(--toggle-width, 60px) * 0.43));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Input as e } from "../Input/Input2.esm.js";
|
|
3
|
+
import './Toggle.css';/* empty css */
|
|
4
|
+
import t from "clsx";
|
|
5
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/Toggle/Toggle.tsx
|
|
7
|
+
var r = ({ labelPosition: r = "right", className: i, style: a, width: o = 40, ...s }) => /* @__PURE__ */ n(e, {
|
|
8
|
+
type: "checkbox",
|
|
9
|
+
labelPosition: r,
|
|
10
|
+
className: t("toggle", i),
|
|
11
|
+
endAdornment: /* @__PURE__ */ n("span", { className: "toggle-slider" }),
|
|
12
|
+
style: {
|
|
13
|
+
...a,
|
|
14
|
+
"--toggle-width": `${o}px`
|
|
15
|
+
},
|
|
16
|
+
...s
|
|
17
|
+
});
|
|
18
|
+
//#endregion
|
|
19
|
+
export { r as Toggle };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Tooltip — Agent Usage Notes
|
|
2
|
+
|
|
3
|
+
> Not yet part of the documented public export surface (see `craftsman-component-usage` skill's Known Limitations). Source path only — do not assume `@stamcat/craftsman/Tooltip` is published until confirmed in `exports.ts`.
|
|
4
|
+
|
|
5
|
+
Import (source-relative, once exported):
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Tooltip } from "@stamcat/craftsman/Tooltip";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Props:
|
|
12
|
+
|
|
13
|
+
- `anchor: React.ReactNode` — the element the tooltip is attached to.
|
|
14
|
+
- `content: React.ReactNode` — the floating content shown.
|
|
15
|
+
- `placement?: Placement` (from `@floating-ui/react-dom`, default: `"bottom-start"`)
|
|
16
|
+
- `strategy?: Strategy` (from `@floating-ui/react-dom`, default: `"absolute"`)
|
|
17
|
+
- `showContent?: "hover" | "click"` (default: `"hover"`)
|
|
18
|
+
- `anchorStyles?: React.CSSProperties`
|
|
19
|
+
- `contentStyles?: React.CSSProperties`
|
|
20
|
+
|
|
21
|
+
Behavior notes:
|
|
22
|
+
|
|
23
|
+
- Built on `@floating-ui/react-dom`'s `useFloating` with `autoUpdate` and `offset(12)`, `flip()`, `shift()` middleware.
|
|
24
|
+
- `showContent="hover"` toggles visibility on the anchor's `mouseenter`/`mouseleave`.
|
|
25
|
+
- `showContent="click"` toggles visibility on anchor click, and closes on any outside `pointerdown`.
|
|
26
|
+
- Floating content is only rendered in the DOM while visible (not just hidden via CSS).
|
|
27
|
+
- Current `placement` is exposed via `data-placement` on the floating element for style targeting.
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<Tooltip
|
|
33
|
+
anchor={<Button variant="text">Hover me</Button>}
|
|
34
|
+
content="Helpful detail"
|
|
35
|
+
placement="top"
|
|
36
|
+
/>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Implementation caution:
|
|
40
|
+
|
|
41
|
+
- No dedicated theme entry currently in `theme.components`; style via `anchorStyles`/`contentStyles` or global selectors targeting `.tooltip__anchor` / `.tooltip__floating`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer craftsman-component{.tooltip{--tooltip-bg:var(--gray800)}.tooltip__floating{background-color:var(--tooltip-bg);color:var(--white);padding:calc(var(--w-gutter) * .25) calc(var(--w-gutter) * .5);border-radius:6px;position:relative}.tooltip__floating:before{content:"";background-color:var(--tooltip-bg);width:8px;height:8px;position:absolute;transform:rotate(45deg)}.tooltip__floating[data-placement^=bottom]:before{margin-left:-4px;top:-4px;left:50%}.tooltip__floating[data-placement^=top]:before{margin-left:-4px;bottom:-4px;left:50%}.tooltip__floating[data-placement^=left]:before{margin-top:-4px;top:50%;right:-4px}.tooltip__floating[data-placement^=right]:before{margin-top:-4px;top:50%;left:-4px}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Placement, Strategy } from '@floating-ui/react-dom';
|
|
2
|
+
import { default as React } from 'react';
|
|
3
|
+
export type TooltipProps = {
|
|
4
|
+
anchor: React.ReactNode;
|
|
5
|
+
content: React.ReactNode;
|
|
6
|
+
placement?: Placement;
|
|
7
|
+
strategy?: Strategy;
|
|
8
|
+
showContent?: "hover" | "click";
|
|
9
|
+
anchorStyles?: React.CSSProperties;
|
|
10
|
+
contentStyles?: React.CSSProperties;
|
|
11
|
+
};
|
|
12
|
+
export declare const Tooltip: React.FC<TooltipProps>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@use "../../styles/utilities/_functions" as u;
|
|
2
|
+
|
|
3
|
+
@layer craftsman-component {
|
|
4
|
+
.tooltip {
|
|
5
|
+
--tooltip-bg: #{u.color("gray800")};
|
|
6
|
+
|
|
7
|
+
&__floating {
|
|
8
|
+
position: relative;
|
|
9
|
+
background-color: var(--tooltip-bg);
|
|
10
|
+
color: #{u.color("white")};
|
|
11
|
+
padding: #{u.width("gutter", 0.25)} #{u.width("gutter", 0.5)};
|
|
12
|
+
border-radius: 6px;
|
|
13
|
+
|
|
14
|
+
&::before {
|
|
15
|
+
content: '';
|
|
16
|
+
position: absolute;
|
|
17
|
+
width: 8px;
|
|
18
|
+
height: 8px;
|
|
19
|
+
background-color: var(--tooltip-bg);
|
|
20
|
+
transform: rotate(45deg);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&[data-placement^="bottom"]::before { top: -4px; left: 50%; margin-left: -4px; }
|
|
24
|
+
&[data-placement^="top"]::before { bottom: -4px; left: 50%; margin-left: -4px; }
|
|
25
|
+
&[data-placement^="left"]::before { right: -4px; top: 50%; margin-top: -4px; }
|
|
26
|
+
&[data-placement^="right"]::before { left: -4px; top: 50%; margin-top: -4px; }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import './Tooltip.css';/* empty css */
|
|
3
|
+
import e from "clsx";
|
|
4
|
+
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
5
|
+
import { useEffect as r, useState as i } from "react";
|
|
6
|
+
import { autoUpdate as a, flip as o, offset as s, shift as c, useFloating as l } from "@floating-ui/react-dom";
|
|
7
|
+
//#region src/components/Tooltip/Tooltip.tsx
|
|
8
|
+
var u = (u) => {
|
|
9
|
+
let { showContent: d = "hover" } = u, [f, p] = i(null), [m, h] = i(null), { floatingStyles: g, placement: _ } = l({
|
|
10
|
+
placement: u.placement ?? "bottom-start",
|
|
11
|
+
strategy: u.strategy ?? "absolute",
|
|
12
|
+
whileElementsMounted: a,
|
|
13
|
+
middleware: [
|
|
14
|
+
s(12),
|
|
15
|
+
o(),
|
|
16
|
+
c()
|
|
17
|
+
],
|
|
18
|
+
elements: {
|
|
19
|
+
reference: f,
|
|
20
|
+
floating: m
|
|
21
|
+
}
|
|
22
|
+
}), [v, y] = i(!1);
|
|
23
|
+
return r(() => {
|
|
24
|
+
if (!v || d !== "click") return;
|
|
25
|
+
let e = (e) => {
|
|
26
|
+
f?.contains(e.target) || m?.contains(e.target) || y(!1);
|
|
27
|
+
};
|
|
28
|
+
return document.addEventListener("pointerdown", e), () => {
|
|
29
|
+
document.removeEventListener("pointerdown", e);
|
|
30
|
+
};
|
|
31
|
+
}, [
|
|
32
|
+
v,
|
|
33
|
+
d,
|
|
34
|
+
f,
|
|
35
|
+
m
|
|
36
|
+
]), /* @__PURE__ */ n("div", {
|
|
37
|
+
className: e("tooltip"),
|
|
38
|
+
children: [/* @__PURE__ */ t("div", {
|
|
39
|
+
className: e("tooltip__anchor"),
|
|
40
|
+
ref: p,
|
|
41
|
+
onMouseEnter: () => {
|
|
42
|
+
d === "hover" && y(!0);
|
|
43
|
+
},
|
|
44
|
+
onMouseLeave: () => {
|
|
45
|
+
d === "hover" && y(!1);
|
|
46
|
+
},
|
|
47
|
+
onClick: () => {
|
|
48
|
+
d === "click" && y((e) => !e);
|
|
49
|
+
},
|
|
50
|
+
style: u.anchorStyles,
|
|
51
|
+
children: u.anchor
|
|
52
|
+
}), v && /* @__PURE__ */ t("div", {
|
|
53
|
+
className: e("tooltip__floating"),
|
|
54
|
+
ref: h,
|
|
55
|
+
"data-placement": _,
|
|
56
|
+
style: {
|
|
57
|
+
...g,
|
|
58
|
+
...u.contentStyles
|
|
59
|
+
},
|
|
60
|
+
children: u.content
|
|
61
|
+
})]
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
export { u as Tooltip };
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
export { Button } from './Button/Button';
|
|
2
2
|
export { Input } from './Input/Input';
|
|
3
|
-
export { InputPassword } from './
|
|
3
|
+
export { InputPassword } from './InputPassword/InputPassword';
|
|
4
4
|
export { Loader } from './Loader/Loader';
|
|
5
|
-
export { RadioButton } from './
|
|
6
|
-
export { Checkbox } from './
|
|
7
|
-
export { Textarea } from './
|
|
5
|
+
export { RadioButton } from './RadioButton/RadioButton';
|
|
6
|
+
export { Checkbox } from './Checkbox/Checkbox';
|
|
7
|
+
export { Textarea } from './Textarea/Textarea';
|
|
8
8
|
export { Text } from './Text/Text';
|
|
9
9
|
export { Modal } from './Modal/Modal';
|
|
10
10
|
export { Select } from './Select/Select';
|
|
11
|
-
export { DatePicker } from './
|
|
12
|
-
export {
|
|
11
|
+
export { DatePicker } from './DatePicker/DatePicker';
|
|
12
|
+
export { DateRangePicker } from './DateRangePicker/DateRangePicker';
|
|
13
|
+
export { InputPhone } from './InputPhone/InputPhone';
|
|
14
|
+
export { InputNumber } from './InputNumber/InputNumber';
|
|
15
|
+
export { Toggle } from './Toggle/Toggle';
|
|
16
|
+
export { Pagination } from './Pagination/Pagination';
|
|
17
|
+
export { Carousel } from './Carousel/Carousel';
|
|
18
|
+
export { TimePicker } from './TimePicker/TimePicker';
|
|
19
|
+
export { DateTimePicker } from './DateTimePicker/DateTimePicker';
|
|
20
|
+
export { Tooltip } from './Tooltip/Tooltip';
|
|
21
|
+
export { Notice } from './Notice/Notice';
|
|
22
|
+
export { SortableList } from './SortableList/SortableList';
|
|
23
|
+
export * from './Icons';
|
|
@@ -7,18 +7,20 @@
|
|
|
7
7
|
background: none;
|
|
8
8
|
color: var(--blue500);
|
|
9
9
|
|
|
10
|
-
&:
|
|
10
|
+
&:hover {
|
|
11
11
|
color: var(--teal700);
|
|
12
12
|
background-color: transparent;
|
|
13
13
|
text-decoration: underline;
|
|
14
14
|
cursor: pointer;
|
|
15
|
+
&.disabled, &:disabled {
|
|
16
|
+
cursor: not-allowed;
|
|
17
|
+
color: #{u.color("gray400")};
|
|
18
|
+
}
|
|
15
19
|
}
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
%button-styles {
|
|
19
|
-
--btn-
|
|
20
|
-
--btn-pad-x: #{u.width(gutter, 0.75)};
|
|
21
|
-
--btn-border-radius: #{u.width(gutter, 0.75)};
|
|
23
|
+
--btn-size: 1;
|
|
22
24
|
color: var(--blue600);
|
|
23
25
|
border: none;
|
|
24
26
|
cursor: pointer;
|
|
@@ -27,15 +29,25 @@
|
|
|
27
29
|
align-items: center;
|
|
28
30
|
font-weight: 500;
|
|
29
31
|
transition: 0.125s;
|
|
30
|
-
padding: var(--btn-
|
|
31
|
-
border-radius: var(--btn-
|
|
32
|
+
padding: calc(#{u.width(gutter, 0.5)} * var(--btn-size)) calc(#{u.width(gutter, 0.75)} * var(--btn-size));
|
|
33
|
+
border-radius: calc(#{u.width(gutter, 0.75)} * var(--btn-size));
|
|
34
|
+
font-size: max(10px, calc(#{u.width(text)} * var(--btn-size)));
|
|
32
35
|
border: 1px solid var(--blue500);
|
|
33
36
|
background-color: var(--white);
|
|
34
37
|
|
|
35
|
-
&:
|
|
38
|
+
&:hover {
|
|
36
39
|
background-color: var(--teal200);
|
|
37
40
|
}
|
|
38
41
|
|
|
42
|
+
&.primary {
|
|
43
|
+
color: var(--white);
|
|
44
|
+
background-color: var(--blue500);
|
|
45
|
+
|
|
46
|
+
&:hover {
|
|
47
|
+
background-color: var(--blue700);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
&.text {
|
|
40
52
|
@extend %text-link;
|
|
41
53
|
}
|
|
@@ -43,22 +55,13 @@
|
|
|
43
55
|
&:disabled,
|
|
44
56
|
&.disabled {
|
|
45
57
|
cursor: not-allowed;
|
|
46
|
-
border-color:
|
|
47
|
-
color:
|
|
58
|
+
border-color: #{u.color("gray200")};
|
|
59
|
+
color: #{u.color("gray400")};
|
|
48
60
|
|
|
49
61
|
&.primary {
|
|
50
|
-
border-color:
|
|
51
|
-
background-color:
|
|
52
|
-
color:
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
&.primary {
|
|
57
|
-
color: var(--white);
|
|
58
|
-
background-color: var(--blue500);
|
|
59
|
-
|
|
60
|
-
&:not(:disabled):not(.disabled):hover {
|
|
61
|
-
background-color: var(--blue700);
|
|
62
|
+
border-color: #{u.color("gray200")};
|
|
63
|
+
background-color: #{u.color("gray400")};
|
|
64
|
+
color: #{u.color("gray200")};
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
}
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
top: 0.08em;
|
|
11
11
|
margin: 0;
|
|
12
12
|
padding: 0;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
--checkbox-size: 1;
|
|
14
|
+
height: calc(#{u.width("gutter")} * var(--checkbox-size));
|
|
15
|
+
width: calc(#{u.width("gutter")} * var(--checkbox-size));
|
|
15
16
|
border-radius: 4px;
|
|
16
17
|
border: 1px solid var(--blue500);
|
|
17
18
|
background: #fff;
|
|
@@ -29,8 +30,8 @@
|
|
|
29
30
|
position: absolute;
|
|
30
31
|
left: 50%;
|
|
31
32
|
top: 45%;
|
|
32
|
-
width: 5px;
|
|
33
|
-
height: 8px;
|
|
33
|
+
width: calc(5px * var(--checkbox-size));
|
|
34
|
+
height: calc(8px * var(--checkbox-size));
|
|
34
35
|
content: "";
|
|
35
36
|
display: block;
|
|
36
37
|
border: solid white;
|
|
@@ -9,16 +9,17 @@
|
|
|
9
9
|
display: inline-grid;
|
|
10
10
|
place-content: center;
|
|
11
11
|
padding: 0;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
--radio-size: 1;
|
|
13
|
+
width: calc(#{u.width("gutter")} * var(--radio-size));
|
|
14
|
+
height: calc(#{u.width("gutter")} * var(--radio-size));
|
|
14
15
|
border: 1px solid var(--blue600);
|
|
15
16
|
border-radius: 50%;
|
|
16
17
|
box-sizing: border-box;
|
|
17
18
|
|
|
18
19
|
&::before {
|
|
19
20
|
content: "";
|
|
20
|
-
width: #{u.width("gutter", 0.5)};
|
|
21
|
-
height: #{u.width("gutter", 0.5)};
|
|
21
|
+
width: calc(#{u.width("gutter", 0.5)} * var(--radio-size));
|
|
22
|
+
height: calc(#{u.width("gutter", 0.5)} * var(--radio-size));
|
|
22
23
|
border-radius: 50%;
|
|
23
24
|
transform: scale(0);
|
|
24
25
|
transition: transform 0.2s ease;
|
|
@@ -11,29 +11,34 @@
|
|
|
11
11
|
@mixin h1 {
|
|
12
12
|
font-size: #{u.width(text, 3.125)};
|
|
13
13
|
line-height: 1.2;
|
|
14
|
+
margin: 0 0 #{u.width(gutter)} 0;
|
|
14
15
|
}
|
|
15
16
|
@mixin h2 {
|
|
16
17
|
font-size: #{u.width(text, 2.625)};
|
|
17
18
|
font-weight: 625;
|
|
18
19
|
line-height: 1.1;
|
|
20
|
+
margin: 0 0 #{u.width(gutter)} 0;
|
|
19
21
|
}
|
|
20
22
|
@mixin h3 {
|
|
21
23
|
font-size: #{u.width(text, 1.625)};
|
|
22
24
|
line-height: 1.1;
|
|
25
|
+
margin: 0 0 #{u.width(gutter, 0.75)} 0;
|
|
23
26
|
}
|
|
24
27
|
@mixin h4 {
|
|
25
28
|
font-size: #{u.width(text, 1.25)};
|
|
26
29
|
line-height: 1.1;
|
|
27
|
-
margin: #{u.width(gutter, 0.5)} 0;
|
|
30
|
+
margin: 0 0 #{u.width(gutter, 0.5)} 0;
|
|
28
31
|
}
|
|
29
32
|
@mixin h5 {
|
|
30
33
|
font-size: var(--w-text);
|
|
31
34
|
line-height: 1.2;
|
|
35
|
+
margin: 0 0 #{u.width(gutter, 0.5)} 0;
|
|
32
36
|
}
|
|
33
37
|
@mixin h6 {
|
|
34
38
|
font-size: #{u.width(text, 0.875)};
|
|
35
39
|
line-height: 1.2;
|
|
36
40
|
font-weight: 600;
|
|
41
|
+
margin: 0;
|
|
37
42
|
}
|
|
38
43
|
@mixin p {
|
|
39
44
|
font-style: normal;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
@use "./components/button";
|
|
7
7
|
@use "./components/input";
|
|
8
8
|
@use "./components/select";
|
|
9
|
-
@layer craftsman-base, craftsman-theme;
|
|
9
|
+
@layer craftsman-base, craftsman-component, craftsman-theme;
|
|
10
10
|
|
|
11
11
|
@layer craftsman-base {
|
|
12
12
|
:root {
|
|
@@ -39,7 +39,9 @@
|
|
|
39
39
|
margin: 0;
|
|
40
40
|
padding: 0;
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
ul {
|
|
43
|
+
list-style: none;
|
|
44
|
+
}
|
|
43
45
|
body {
|
|
44
46
|
@include t.body-typography;
|
|
45
47
|
background-color: #fff;
|
|
@@ -61,9 +63,7 @@
|
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
input {
|
|
64
|
-
|
|
65
|
-
@extend %input-base;
|
|
66
|
-
}
|
|
66
|
+
@extend %input-base;
|
|
67
67
|
&[type="checkbox"] {
|
|
68
68
|
@extend %checkbox;
|
|
69
69
|
}
|
|
@@ -72,6 +72,10 @@
|
|
|
72
72
|
@extend %radio;
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
figure {
|
|
76
|
+
margin: 0;
|
|
77
|
+
|
|
78
|
+
}
|
|
75
79
|
textarea {
|
|
76
80
|
@extend %input-base;
|
|
77
81
|
}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { components_exports as e } from "../../../Components.esm.js";
|
|
2
|
+
import { htmlTagNames as t } from "./constants.esm.js";
|
|
3
3
|
//#region src/styles/theme/components.ts
|
|
4
4
|
var n = {
|
|
5
|
-
input: "input:not([type='radio']):not([type='checkbox'])",
|
|
6
5
|
checkbox: "input[type='checkbox']",
|
|
7
6
|
radioButton: "input[type='radio']"
|
|
8
7
|
};
|
|
9
8
|
function r(e) {
|
|
10
9
|
return e.charAt(0).toLowerCase() + e.slice(1);
|
|
11
10
|
}
|
|
12
|
-
function i(
|
|
13
|
-
return n[
|
|
11
|
+
function i(e) {
|
|
12
|
+
return n[e] || (t.has(e) ? `${e}, .${e}` : `.${e}`);
|
|
14
13
|
}
|
|
15
|
-
var a = Object.keys(
|
|
14
|
+
var a = Object.keys(e).map(r), o = Object.fromEntries(a.map((e) => [e, i(e)]));
|
|
16
15
|
//#endregion
|
|
17
16
|
export { o as componentSelectors };
|
|
@@ -21,7 +21,7 @@ $width-defaults: (
|
|
|
21
21
|
|
|
22
22
|
@return string.unquote("var(--#{$name})");
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
// internal function
|
|
25
25
|
@function width-var($name) {
|
|
26
26
|
@if not map.has-key($width-defaults, $name) {
|
|
27
27
|
@error "Unknown width key `#{$name}`.";
|
|
@@ -59,7 +59,7 @@ $width-defaults: (
|
|
|
59
59
|
|
|
60
60
|
@return string.unquote("calc(#{$value} * #{$multiplier})");
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
// internal function
|
|
63
63
|
@function media($bp) {
|
|
64
64
|
@if $bp == mobile {
|
|
65
65
|
@return string.unquote("(min-width: 0px)");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { LayoutWidthsSchema as e } from "../../utilities/types.esm.js";
|
|
2
|
+
import { defaultWidths as t } from "./constants.esm.js";
|
|
3
3
|
//#region src/styles/utilities/layout.ts
|
|
4
|
-
var n = Object.fromEntries(
|
|
4
|
+
var n = Object.fromEntries(e.options.map((e) => [e, `var(--w-${e}, ${t[e]}px)`])), r = {
|
|
5
5
|
get mobile() {
|
|
6
6
|
return "(min-width: 0px)";
|
|
7
7
|
},
|