@senestia/ui 0.1.0-beta.0190ae9 → 0.1.0-beta.0c3734c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/senestia-ui.es.js
CHANGED
|
@@ -412,7 +412,7 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
412
412
|
search: i,
|
|
413
413
|
password: n
|
|
414
414
|
}, O = ({ label: n, required: i = !1, labelRemark: a, placeholder: o = "Placeholder", value: l, onChange: u, helperText: d, errorText: f, state: p = "Idle", size: m = "md", leadingDropdownText: h, leadingIcon: v, counter: y, unit: x, trailingIcon: S, trailingIcons: O, trailingIconSeparator: k = !1 }) => {
|
|
415
|
-
let { isInvalid: A, isHover: j, isActive: M, isDisabled: N, isSkeleton: P, isKeyboardFocus: F } = E(p), I = w[m], L = A ? b.invalidBorder : M || F ? b.activeBorder : j ? b.hoverBorder : g.borderMidgray, R = N ? g.bgDisabled : j ? g.bgLightgray : g.bgWhite, z = N ? g.fgLow : g.fgMid, B =
|
|
415
|
+
let { isInvalid: A, isHover: j, isActive: M, isDisabled: N, isSkeleton: P, isKeyboardFocus: F } = E(p), I = w[m], L = A ? b.invalidBorder : M || F ? b.activeBorder : j ? b.hoverBorder : g.borderMidgray, R = N ? g.bgDisabled : j ? g.bgLightgray : g.bgWhite, z = N ? g.fgLow : g.fgMid, B = N ? g.fgLow : g.fgHigh, V = N ? g.fgLow : g.fgHigh, H = N ? g.fgLow : g.fgMid, U = A ? _.error : g.fgMid;
|
|
416
416
|
if (P) return /* @__PURE__ */ c("div", {
|
|
417
417
|
style: {
|
|
418
418
|
width: 320,
|
|
@@ -431,7 +431,7 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
431
431
|
borderRadius: 24
|
|
432
432
|
} })]
|
|
433
433
|
});
|
|
434
|
-
let
|
|
434
|
+
let W = v === !0 ? t : v || null, G = O?.length ? O : S ? [S] : [], K = A ? f : d, q = {
|
|
435
435
|
fontFamily: C,
|
|
436
436
|
fontWeight: 500
|
|
437
437
|
};
|
|
@@ -467,7 +467,7 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
467
467
|
},
|
|
468
468
|
children: [/* @__PURE__ */ s("span", {
|
|
469
469
|
style: {
|
|
470
|
-
...
|
|
470
|
+
...q,
|
|
471
471
|
fontSize: I.labelFontSize,
|
|
472
472
|
lineHeight: `${I.labelLineHeight}px`,
|
|
473
473
|
color: z,
|
|
@@ -478,14 +478,14 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
478
478
|
children: n
|
|
479
479
|
}), /* @__PURE__ */ s(r, {
|
|
480
480
|
size: I.labelIconSize,
|
|
481
|
-
color:
|
|
481
|
+
color: H,
|
|
482
482
|
strokeWidth: 1.8,
|
|
483
483
|
style: { flexShrink: 0 }
|
|
484
484
|
})]
|
|
485
485
|
}),
|
|
486
486
|
a && /* @__PURE__ */ s("span", {
|
|
487
487
|
style: {
|
|
488
|
-
...
|
|
488
|
+
...q,
|
|
489
489
|
fontSize: I.labelFontSize,
|
|
490
490
|
lineHeight: `${I.labelLineHeight}px`,
|
|
491
491
|
color: z,
|
|
@@ -532,7 +532,7 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
532
532
|
},
|
|
533
533
|
children: [/* @__PURE__ */ s("span", {
|
|
534
534
|
style: {
|
|
535
|
-
...
|
|
535
|
+
...q,
|
|
536
536
|
fontSize: I.inputFontSize,
|
|
537
537
|
lineHeight: `${I.inputLineHeight}px`,
|
|
538
538
|
color: g.fgHigh,
|
|
@@ -552,9 +552,9 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
552
552
|
strokeLinejoin: "round"
|
|
553
553
|
})
|
|
554
554
|
})]
|
|
555
|
-
}) :
|
|
555
|
+
}) : W ? /* @__PURE__ */ s(W, {
|
|
556
556
|
size: I.iconSize,
|
|
557
|
-
color:
|
|
557
|
+
color: V,
|
|
558
558
|
strokeWidth: 1.6,
|
|
559
559
|
style: { flexShrink: 0 }
|
|
560
560
|
}) : null, /* @__PURE__ */ c("div", {
|
|
@@ -571,27 +571,28 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
571
571
|
} : {}
|
|
572
572
|
},
|
|
573
573
|
children: [
|
|
574
|
-
/* @__PURE__ */ s("
|
|
574
|
+
/* @__PURE__ */ s("input", {
|
|
575
|
+
type: "text",
|
|
576
|
+
value: l ?? "",
|
|
577
|
+
onChange: (e) => u?.(e.target.value),
|
|
578
|
+
placeholder: o,
|
|
579
|
+
disabled: N,
|
|
575
580
|
style: {
|
|
581
|
+
...q,
|
|
576
582
|
flex: "1 0 0",
|
|
583
|
+
border: "none",
|
|
584
|
+
outline: "none",
|
|
585
|
+
background: "transparent",
|
|
586
|
+
fontSize: I.inputFontSize,
|
|
587
|
+
lineHeight: `${I.inputLineHeight}px`,
|
|
588
|
+
color: B,
|
|
589
|
+
width: "100%",
|
|
590
|
+
minWidth: 0,
|
|
577
591
|
overflow: "hidden",
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
style: {
|
|
583
|
-
...J,
|
|
584
|
-
fontSize: I.inputFontSize,
|
|
585
|
-
lineHeight: `${I.inputLineHeight}px`,
|
|
586
|
-
color: l ? V : B,
|
|
587
|
-
overflow: "hidden",
|
|
588
|
-
textOverflow: "ellipsis",
|
|
589
|
-
whiteSpace: "nowrap",
|
|
590
|
-
display: "block",
|
|
591
|
-
width: "100%"
|
|
592
|
-
},
|
|
593
|
-
children: l || o
|
|
594
|
-
})
|
|
592
|
+
textOverflow: "ellipsis",
|
|
593
|
+
whiteSpace: "nowrap",
|
|
594
|
+
cursor: N ? "not-allowed" : "text"
|
|
595
|
+
}
|
|
595
596
|
}),
|
|
596
597
|
y && /* @__PURE__ */ c("div", {
|
|
597
598
|
style: {
|
|
@@ -607,7 +608,7 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
607
608
|
},
|
|
608
609
|
children: [/* @__PURE__ */ s("span", {
|
|
609
610
|
style: {
|
|
610
|
-
...
|
|
611
|
+
...q,
|
|
611
612
|
fontSize: I.counterFontSize,
|
|
612
613
|
lineHeight: `${I.counterLineHeight}px`,
|
|
613
614
|
color: g.fgHigh
|
|
@@ -615,7 +616,7 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
615
616
|
children: y.value
|
|
616
617
|
}), /* @__PURE__ */ c("span", {
|
|
617
618
|
style: {
|
|
618
|
-
...
|
|
619
|
+
...q,
|
|
619
620
|
fontSize: I.counterFontSize,
|
|
620
621
|
lineHeight: `${I.counterLineHeight}px`,
|
|
621
622
|
color: g.fgMid
|
|
@@ -625,7 +626,7 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
625
626
|
}),
|
|
626
627
|
x && /* @__PURE__ */ s("span", {
|
|
627
628
|
style: {
|
|
628
|
-
...
|
|
629
|
+
...q,
|
|
629
630
|
fontSize: I.inputFontSize,
|
|
630
631
|
lineHeight: `${I.inputLineHeight}px`,
|
|
631
632
|
color: g.fgHigh,
|
|
@@ -636,14 +637,14 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
636
637
|
},
|
|
637
638
|
children: x
|
|
638
639
|
}),
|
|
639
|
-
|
|
640
|
+
G.length > 0 && /* @__PURE__ */ s("div", {
|
|
640
641
|
style: {
|
|
641
642
|
display: "flex",
|
|
642
643
|
alignItems: "center",
|
|
643
644
|
gap: 4,
|
|
644
645
|
flexShrink: 0
|
|
645
646
|
},
|
|
646
|
-
children:
|
|
647
|
+
children: G.map((t, n) => {
|
|
647
648
|
let r = D[t];
|
|
648
649
|
return /* @__PURE__ */ c(e.Fragment, { children: [k && n > 0 && /* @__PURE__ */ s("div", { style: {
|
|
649
650
|
width: 1,
|
|
@@ -653,7 +654,7 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
653
654
|
alignSelf: "center"
|
|
654
655
|
} }), /* @__PURE__ */ s(r, {
|
|
655
656
|
size: I.iconSize,
|
|
656
|
-
color:
|
|
657
|
+
color: V,
|
|
657
658
|
strokeWidth: 1.6,
|
|
658
659
|
style: { flexShrink: 0 }
|
|
659
660
|
})] }, `${t}-${n}`);
|
|
@@ -662,16 +663,16 @@ var l = Object.defineProperty, u = (e, t) => {
|
|
|
662
663
|
]
|
|
663
664
|
})]
|
|
664
665
|
})]
|
|
665
|
-
}),
|
|
666
|
+
}), K && /* @__PURE__ */ s("p", {
|
|
666
667
|
style: {
|
|
667
|
-
...
|
|
668
|
+
...q,
|
|
668
669
|
margin: 0,
|
|
669
670
|
fontSize: I.helperFontSize,
|
|
670
671
|
lineHeight: `${I.helperLineHeight}px`,
|
|
671
|
-
color:
|
|
672
|
+
color: U,
|
|
672
673
|
width: "100%"
|
|
673
674
|
},
|
|
674
|
-
children:
|
|
675
|
+
children: K
|
|
675
676
|
})]
|
|
676
677
|
});
|
|
677
678
|
}, k = h;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"senestia-ui.es.js","names":[],"sources":["../src/stories/Badge.tsx","../src/stories/tokens.ts","../src/stories/InputField.tsx","../src/index.ts"],"sourcesContent":["import React from 'react';\nimport { X } from 'lucide-react';\n\n// ─── Design System Font ──────────────────────────────────────────────────────\nconst font = 'Sarabun, sans-serif';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type BadgeColor =\n | 'Gray'\n | 'Primary'\n | 'Error'\n | 'Warning'\n | 'Success'\n | 'Blue light'\n | 'Blue'\n | 'Indigo'\n | 'Purple'\n | 'Pink'\n | 'Orange'\n | 'Gray blue';\n\nexport type BadgeSize = 'sm' | 'md' | 'lg';\n\nexport type BadgeType = 'Idle' | 'Status Dot' | 'Closable' | 'Pill color';\n\nexport interface BadgeProps {\n /** Badge label text */\n label?: string;\n /** Color variant */\n color?: BadgeColor;\n /** Size variant */\n size?: BadgeSize;\n /** Type / style variant */\n type?: BadgeType;\n /** Icon to render inside Pill color type (Lucide icon component) */\n icon?: React.ElementType;\n /** Called when close button is clicked (Closable type) */\n onClose?: () => void;\n}\n\n// ─── Color Tokens ────────────────────────────────────────────────────────────\n\nconst COLOR_TOKENS: Record<\n BadgeColor,\n { bg: string; border: string; text: string; dot: string }\n> = {\n Gray: { bg: '#f9fafb', border: '#eaecf0', text: '#06080b', dot: '#667085' },\n Primary: { bg: '#f4f6f9', border: '#e6ebf2', text: '#1e2b3b', dot: '#6c8fbe' },\n Error: { bg: '#fef0ef', border: '#fbd2d0', text: '#cc1a11', dot: '#f04438' },\n Warning: { bg: '#fff9ee', border: '#ffedcc', text: '#db8f02', dot: '#f79009' },\n Success: { bg: '#f0fdfa', border: '#d2f9f1', text: '#15a686', dot: '#12b76a' },\n 'Blue light': { bg: '#f0f9ff', border: '#b9e6fe', text: '#026aa2', dot: '#0ba5ec' },\n Blue: { bg: '#eff8ff', border: '#b2ddff', text: '#175cd3', dot: '#2e90fa' },\n Indigo: { bg: '#eef4ff', border: '#c7d7fe', text: '#3538cd', dot: '#6172f3' },\n Purple: { bg: '#f4f3ff', border: '#d9d6fe', text: '#5925dc', dot: '#7a5af8' },\n Pink: { bg: '#fef6fb', border: '#fce7f6', text: '#c11574', dot: '#ee46bc' },\n Orange: { bg: '#fef6ee', border: '#ffd6ae', text: '#b93815', dot: '#ef6820' },\n 'Gray blue':{ bg: '#f8f9fc', border: '#d5d9eb', text: '#363f72', dot: '#717bbc' },\n};\n\n// ─── Size Tokens ─────────────────────────────────────────────────────────────\n\nconst SIZE_TOKENS: Record<\n BadgeSize,\n {\n paddingX: number;\n paddingY: number;\n paddingXClose: { left: number; right: number };\n paddingXDot: { left: number; right: number };\n paddingPill: number;\n fontSize: number;\n lineHeight: number;\n dotSize: number;\n iconSize: number;\n closeSize: number;\n }\n> = {\n sm: {\n paddingX: 8, paddingY: 2,\n paddingXClose: { left: 8, right: 4 },\n paddingXDot: { left: 6, right: 8 },\n paddingPill: 5,\n fontSize: 12, lineHeight: 18,\n dotSize: 6, iconSize: 12, closeSize: 12,\n },\n md: {\n paddingX: 8, paddingY: 2,\n paddingXClose: { left: 8, right: 4 },\n paddingXDot: { left: 6, right: 8 },\n paddingPill: 6,\n fontSize: 14, lineHeight: 20,\n dotSize: 6, iconSize: 14, closeSize: 14,\n },\n lg: {\n paddingX: 12, paddingY: 4,\n paddingXClose: { left: 12, right: 6 },\n paddingXDot: { left: 8, right: 12 },\n paddingPill: 8,\n fontSize: 14, lineHeight: 20,\n dotSize: 8, iconSize: 16, closeSize: 16,\n },\n};\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport const Badge: React.FC<BadgeProps> = ({\n label = 'Label',\n color = 'Gray',\n size = 'sm',\n type = 'Idle',\n icon: IconComponent,\n onClose,\n}) => {\n const c = COLOR_TOKENS[color];\n const s = SIZE_TOKENS[size];\n\n // ── Shared wrapper style ──────────────────────────────────────────────────\n const baseWrapper: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n backgroundColor: c.bg,\n border: `1px solid ${c.border}`,\n borderRadius: 16,\n boxSizing: 'border-box',\n width: 'fit-content',\n fontFamily: font,\n };\n\n // ── Text style ────────────────────────────────────────────────────────────\n const textStyle: React.CSSProperties = {\n fontSize: s.fontSize,\n lineHeight: `${s.lineHeight}px`,\n fontWeight: 500,\n color: c.text,\n whiteSpace: 'nowrap',\n fontFamily: font,\n margin: 0,\n };\n\n // ── Idle ─────────────────────────────────────────────────────────────────\n if (type === 'Idle') {\n return (\n <span\n style={{\n ...baseWrapper,\n padding: `${s.paddingY}px ${s.paddingX}px`,\n }}\n >\n <span style={textStyle}>{label}</span>\n </span>\n );\n }\n\n // ── Status Dot ────────────────────────────────────────────────────────────\n if (type === 'Status Dot') {\n return (\n <span\n style={{\n ...baseWrapper,\n gap: 4,\n paddingTop: s.paddingY,\n paddingBottom: s.paddingY,\n paddingLeft: s.paddingXDot.left,\n paddingRight: s.paddingXDot.right,\n }}\n >\n {/* Dot */}\n <span\n style={{\n display: 'inline-block',\n width: s.dotSize,\n height: s.dotSize,\n borderRadius: '50%',\n backgroundColor: c.dot,\n flexShrink: 0,\n }}\n />\n <span style={textStyle}>{label}</span>\n </span>\n );\n }\n\n // ── Closable ──────────────────────────────────────────────────────────────\n if (type === 'Closable') {\n return (\n <span\n style={{\n ...baseWrapper,\n gap: 2,\n paddingTop: s.paddingY,\n paddingBottom: s.paddingY,\n paddingLeft: s.paddingXClose.left,\n paddingRight: s.paddingXClose.right,\n }}\n >\n <span style={textStyle}>{label}</span>\n <button\n onClick={onClose}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'none',\n border: 'none',\n padding: 2,\n borderRadius: 3,\n cursor: 'pointer',\n color: c.text,\n flexShrink: 0,\n lineHeight: 1,\n }}\n aria-label=\"Remove\"\n >\n <X size={s.closeSize} strokeWidth={2.5} />\n </button>\n </span>\n );\n }\n\n // ── Pill color (icon only) ────────────────────────────────────────────────\n if (type === 'Pill color') {\n const PillIcon = IconComponent;\n return (\n <span\n style={{\n ...baseWrapper,\n padding: s.paddingPill,\n }}\n >\n {PillIcon ? (\n <PillIcon size={s.iconSize} color={c.dot} strokeWidth={2} />\n ) : (\n // Default: colored circle dot\n <span\n style={{\n display: 'inline-block',\n width: s.iconSize,\n height: s.iconSize,\n borderRadius: '50%',\n backgroundColor: c.dot,\n }}\n />\n )}\n </span>\n );\n }\n\n return null;\n};\n","/**\n * Senestia Design System — Semantic Color Tokens\n *\n * ┌─────────────────────────────────────────────────────────────┐\n * │ Source: Figma DS-01 · Foundation → Semantic Color │\n * │ Use these tokens in components instead of raw hex values. │\n * └─────────────────────────────────────────────────────────────┘\n */\n\n// ─── Gray-Neutral ─────────────────────────────────────────────────────────────\n\nexport const grayNeutral = {\n /** Semantic/Gray-Neutral/fg/high — primary text, dark icons */\n fgHigh: '#1B1D22',\n /** Semantic/Gray-Neutral/fg/mid-on-white — label text, helper text, secondary icons */\n fgMid: '#6A6E83',\n /** Semantic/Gray-Neutral/fg/low-on-white — placeholder, disabled text */\n fgLow: '#9A9DAD',\n\n /** Semantic/Gray-Neutral/bg/white */\n bgWhite: '#FFFFFF',\n /** Semantic/Gray-Neutral/bg/lightgray — counter pill, subtle backgrounds */\n bgLightgray: '#F8F8F9',\n /** Semantic/Gray-Neutral/bg/disabled */\n bgDisabled: '#F3F4F6',\n\n /** Semantic/Gray-Neutral/border/midgray — default input border */\n borderMidgray: '#CFD1D9',\n /** Semantic/Gray-Neutral/border/light — dividers, card borders */\n borderLight: '#EBECEF',\n /** Disabled border (checkbox, input) */\n borderDisabled: '#E5EAF1',\n\n /** Gray/300 — icon separators */\n gray300: '#D0D5DD',\n /** Skeleton loading shimmer */\n bgSkeleton: '#EEF0F3',\n /** Strong disabled background (checkbox) */\n bgDisabledStrong: '#EBECEF',\n} as const;\n\n// ─── Status ───────────────────────────────────────────────────────────────────\n\nexport const status = {\n /** Error / invalid state */\n error: '#DB1439',\n /** Warning */\n warning: '#DB8F02',\n /** Success */\n success: '#15A686',\n} as const;\n\n// ─── CI Primary (Senestia brand purple) ───────────────────────────────────────\n\nexport const ciPrimary = {\n fgLow: '#C4B3F6',\n fgHigh: '#802CEB',\n bgLow: '#D4C9F6',\n bgMid: '#802CEB',\n bgHigh: '#5A1DA9',\n borderMid: '#996CF3',\n borderHigh: '#802CEB',\n} as const;\n\n// ─── OE Theme (OE brand blue) ─────────────────────────────────────────────────\n\nexport const oePrimary = {\n fgLow: '#5273A1',\n fgHigh: '#3A5274',\n bgLowest: '#EFF2F6', // selected item background in pickers\n bgLow: '#6E90BF',\n bgMid: '#5273A1',\n bgHigh: '#3A5274',\n borderLowest:'#C6D2E3', // focused item border\n borderLow: '#9CB3D2',\n borderMid: '#5273A1',\n /** Primary/300 — supporting/helper text on blue-tinted UI */\n p300: '#809BBF',\n /** Indigo/300 — \"Set to now\" link color */\n linkBlue: '#3C5BD5',\n} as const;\n\n// ─── Interactive states ───────────────────────────────────────────────────────\n\nexport const interactive = {\n /** Active / focused border */\n activeBorder: oePrimary.fgLow, // #5273A1\n /** Hover border */\n hoverBorder: '#3B82F6',\n /** Focus ring shadow */\n focusRing: '#D7DFEA',\n /** Invalid border */\n invalidBorder: status.error,\n} as const;\n\n// ─── Padding tokens (PD) ─────────────────────────────────────────────────────\n\nexport const padding = {\n 'PD-0': 0,\n 'PD-1': 1,\n 'PD-2': 2,\n 'PD-3': 4,\n 'PD-4': 6,\n 'PD-5': 8,\n 'PD-6': 12,\n 'PD-7': 16,\n 'PD-8': 24,\n 'PD-9': 32,\n 'PD-10': 40,\n 'PD-11': 48,\n 'PD-12': 56,\n 'PD-13': 64,\n 'PD-14': 72,\n 'PD-15': 80,\n} as const;\n\n// ─── Corner Radius tokens (CR) ───────────────────────────────────────────────\n\nexport const radius = {\n 'CR-0': 0,\n 'CR-1': 2,\n 'CR-2': 4,\n 'CR-3': 8,\n 'CR-4': 12,\n 'CR-5': 16,\n 'CR-6': 20,\n 'CR-7': 24,\n 'CR-8': 32,\n 'CR-9': 48,\n 'CR-10': 100,\n} as const;\n\n// ─── Typography ───────────────────────────────────────────────────────────────\n\nexport const font = 'Sarabun, sans-serif';\n","import React from 'react';\nimport { Circle, Info, XCircle, Search, Eye } from 'lucide-react';\nimport { grayNeutral, status, interactive, font } from './tokens';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type InputFieldState =\n | 'Idle'\n | 'Idle hover'\n | 'Active'\n | 'Idle invalid'\n | 'Idle invalid hover'\n | 'Idle invalid active'\n | 'Filled'\n | 'Filled hover'\n | 'Filled active'\n | 'Filled invalid'\n | 'Filled invalid hover'\n | 'Filled invalid active'\n | 'Disable'\n | 'Keyboard focus'\n | 'Skeleton';\n\nexport type InputFieldSize = 'sm' | 'md' | 'lg';\n\nexport type InputFieldTrailingIcon = 'clear' | 'password' | 'search';\n\nexport type InputFieldCounter = {\n value: number;\n max: number;\n};\n\nexport interface InputFieldProps {\n /** Label text displayed above the input */\n label: string;\n /** Show required asterisk (*) */\n required?: boolean;\n /** Remark text next to label e.g. \"(optional)\" */\n labelRemark?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Current value */\n value?: string;\n /** Called when value changes */\n onChange?: (value: string) => void;\n /** Helper text below the input (hidden when invalid) */\n helperText?: string;\n /** Error message below the input (shown when invalid state) */\n errorText?: string;\n /** Visual state from Figma */\n state?: InputFieldState;\n /** Input size — affects height, font, and padding */\n size?: InputFieldSize;\n /** Leading dropdown prefix text */\n leadingDropdownText?: string;\n /**\n * Leading icon inside the input (left side).\n * - `true` → default Circle icon\n * - `React.ElementType` → custom Lucide icon\n * - `false/undefined` → no icon\n */\n leadingIcon?: React.ElementType | boolean;\n /** Counter pill e.g. `{ value: 0, max: 20 }` */\n counter?: InputFieldCounter;\n /** Unit text inside the input */\n unit?: string;\n /** Single trailing icon */\n trailingIcon?: InputFieldTrailingIcon;\n /** Multiple trailing icons (overrides trailingIcon) */\n trailingIcons?: InputFieldTrailingIcon[];\n /** Show separator between trailing icons */\n trailingIconSeparator?: boolean;\n}\n\n// ─── Design tokens (from Figma) ──────────────────────────────────────────────\n\n/**\n * Size tokens — matched to Figma nodes:\n * sm (Sm-32): label C5 12/18 · input C4 14/20 · helper C5 12/18\n * md (Md-40): label C4 14/20 · input C3 16/24 · helper C4 14/20\n * lg (Lg-48): label C3 16/24 · input C3 16/24 · helper C4 14/20\n *\n * Spacing (per Figma sm node — gap-4 between all elements):\n * labelGap = gap between label row and input box\n * helperGap = gap between input box and helper/error text\n */\nconst sizeTokens = {\n sm: {\n inputHeight: 32,\n labelFontSize: 12, labelLineHeight: 18,\n inputFontSize: 14, inputLineHeight: 20,\n helperFontSize: 12, helperLineHeight: 18,\n paddingX: 12,\n iconSize: 16,\n labelIconSize: 12,\n labelGap: 4, // label row → input\n helperGap: 4, // input → helper text\n leadingPl: 8, leadingPr: 4, leadingPy: 6,\n chevronSize: 14,\n counterPadding: '1px 4px',\n counterRadius: 4,\n counterFontSize: 12, counterLineHeight: 18,\n skeletonLabelH: 18, skeletonInputH: 32,\n },\n md: {\n inputHeight: 40,\n labelFontSize: 14, labelLineHeight: 20,\n inputFontSize: 16, inputLineHeight: 24,\n helperFontSize: 14, helperLineHeight: 20,\n paddingX: 16,\n iconSize: 20,\n labelIconSize: 14,\n labelGap: 6, // label row → input\n helperGap: 4, // input → helper text\n leadingPl: 12, leadingPr: 8, leadingPy: 8,\n chevronSize: 16,\n counterPadding: '2px 8px',\n counterRadius: 8,\n counterFontSize: 14, counterLineHeight: 20,\n skeletonLabelH: 20, skeletonInputH: 40,\n },\n lg: {\n inputHeight: 48,\n labelFontSize: 16, labelLineHeight: 24,\n inputFontSize: 16, inputLineHeight: 24,\n helperFontSize: 14, helperLineHeight: 20,\n paddingX: 16,\n iconSize: 20,\n labelIconSize: 16,\n labelGap: 8, // label row → input\n helperGap: 6, // input → helper text\n leadingPl: 16, leadingPr: 8, leadingPy: 12,\n chevronSize: 16,\n counterPadding: '2px 8px',\n counterRadius: 8,\n counterFontSize: 14, counterLineHeight: 20,\n skeletonLabelH: 24, skeletonInputH: 48,\n },\n} as const;\n\n// ─── State helpers ────────────────────────────────────────────────────────────\n\nconst focusRingStyle = `0 0 0 2px ${interactive.focusRing}`;\n\nconst getStateFlags = (state: InputFieldState | undefined) => {\n const s = state ?? 'Idle';\n const isInvalid = s.includes('invalid');\n const isHover = s.includes('hover');\n const isActive = s === 'Active' || s === 'Keyboard focus' || s.endsWith('active');\n const isDisabled = s === 'Disable';\n const isSkeleton = s === 'Skeleton';\n const isFilled = s.includes('Filled');\n const isKeyboardFocus = s === 'Keyboard focus';\n return { s, isInvalid, isHover, isActive, isDisabled, isSkeleton, isFilled, isKeyboardFocus };\n};\n\n// ─── Trailing icon map → Lucide ───────────────────────────────────────────────\n\nconst TRAILING_ICON_MAP = {\n clear: XCircle,\n search: Search,\n password: Eye,\n} as const;\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport const InputField = ({\n label,\n required = false,\n labelRemark,\n placeholder = 'Placeholder',\n value,\n onChange: _onChange,\n helperText,\n errorText,\n state = 'Idle',\n size = 'md',\n leadingDropdownText,\n leadingIcon,\n counter,\n unit,\n trailingIcon,\n trailingIcons,\n trailingIconSeparator = false,\n}: InputFieldProps) => {\n const { isInvalid, isHover, isActive, isDisabled, isSkeleton, isKeyboardFocus } =\n getStateFlags(state);\n\n const t = sizeTokens[size];\n\n // ── Colors — mapped to Semantic/Gray-Neutral tokens ─────────────────────\n const borderColor = isInvalid\n ? interactive.invalidBorder // status.error #DB1439\n : isActive || isKeyboardFocus\n ? interactive.activeBorder // oePrimary.fgLow #5273A1\n : isHover\n ? interactive.hoverBorder // #3B82F6\n : grayNeutral.borderMidgray; // #CFD1D9\n\n const background = isDisabled\n ? grayNeutral.bgDisabled // #F3F4F6\n : isHover\n ? grayNeutral.bgLightgray // #F8F8F9\n : grayNeutral.bgWhite; // #FFFFFF\n\n // Label text → fg/mid-on-white (disabled → fg/low)\n const labelColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgMid;\n\n // Placeholder → fg/low-on-white (same whether disabled or not)\n const placeholderColor = grayNeutral.fgLow; // #9A9DAD\n\n // Typed value → fg/high (disabled → fg/low)\n const valueColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgHigh; // #1B1D22\n\n // ── Icon colors (Figma: Semantic/Gray-Neutral/fg/high for input icons) ───\n // Input leading/trailing icons → fg/high (#1B1D22)\n const inputIconColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgHigh;\n // Label info icon → fg/mid (same as label text, #6A6E83)\n const labelIconColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgMid;\n\n const helperColor = isInvalid ? status.error : grayNeutral.fgMid; // #6A6E83\n\n // ── Skeleton ─────────────────────────────────────────────────────────────\n if (isSkeleton) {\n return (\n <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: t.labelGap }}>\n <div style={{ height: t.skeletonLabelH, background: grayNeutral.bgSkeleton, borderRadius: 6 }} />\n <div style={{ height: t.skeletonInputH, background: grayNeutral.bgSkeleton, border: `1px solid ${grayNeutral.bgSkeleton}`, borderRadius: 24 }} />\n </div>\n );\n }\n\n // ── Leading icon resolve ──────────────────────────────────────────────────\n // true → Circle (Figma default \"Icon/circle\"), component → custom, false → none\n const LeadingIconComponent: React.ElementType | null =\n leadingIcon === true\n ? Circle\n : leadingIcon\n ? (leadingIcon as React.ElementType)\n : null;\n\n // ── Trailing icons ────────────────────────────────────────────────────────\n const iconsToRender: InputFieldTrailingIcon[] =\n trailingIcons?.length ? trailingIcons : trailingIcon ? [trailingIcon] : [];\n\n // ── Text below input ──────────────────────────────────────────────────────\n const showText = isInvalid ? errorText : helperText;\n\n // ── Shared font style ─────────────────────────────────────────────────────\n const baseFont: React.CSSProperties = { fontFamily: font, fontWeight: 500 };\n\n return (\n /*\n * Outer wrapper — two-level gap structure matching Figma:\n * Level 1 (helperGap): separates [label + input block] from [helper text]\n * Level 2 (labelGap): separates [label row] from [input box]\n */\n <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: t.helperGap }}>\n\n {/* ── Level 1: label + input block ────────────────────────────────── */}\n <div style={{ display: 'flex', flexDirection: 'column', gap: t.labelGap, width: '100%' }}>\n\n {/* Label row */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, width: '100%' }}>\n {/* Left: label text + info icon */}\n <div style={{ display: 'flex', flex: '1 0 0', alignItems: 'center', gap: t.labelIconSize === 12 ? 4 : 6, minWidth: 0 }}>\n <span\n style={{\n ...baseFont,\n fontSize: t.labelFontSize,\n lineHeight: `${t.labelLineHeight}px`,\n color: labelColor,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {label}\n </span>\n {/* Info icon — fg/mid-on-white (same shade as label text) */}\n <Info\n size={t.labelIconSize}\n color={labelIconColor}\n strokeWidth={1.8}\n style={{ flexShrink: 0 }}\n />\n </div>\n\n {/* Right: remark or required marker */}\n {labelRemark && (\n <span\n style={{\n ...baseFont,\n fontSize: t.labelFontSize,\n lineHeight: `${t.labelLineHeight}px`,\n color: labelColor,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n }}\n >\n {labelRemark}\n </span>\n )}\n {required && (\n <span style={{ color: status.error, fontWeight: 800, flexShrink: 0 }}>*</span>\n )}\n </div>\n\n {/* Input box */}\n <div\n style={{\n background,\n border: `1px solid ${borderColor}`,\n height: t.inputHeight,\n width: '100%',\n borderRadius: 24,\n display: 'flex',\n alignItems: leadingDropdownText ? 'stretch' : 'center',\n ...(leadingDropdownText ? {} : { gap: 8, padding: `0 ${t.paddingX}px` }),\n overflow: 'hidden',\n boxShadow: isActive || isKeyboardFocus ? focusRingStyle : 'none',\n opacity: isDisabled ? 0.7 : 1,\n boxSizing: 'border-box',\n }}\n >\n {/* Leading: dropdown prefix OR icon */}\n {leadingDropdownText ? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n background: grayNeutral.bgWhite,\n padding: `${t.leadingPy}px ${t.leadingPr}px ${t.leadingPy}px ${t.leadingPl}px`,\n flexShrink: 0,\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: grayNeutral.fgHigh,\n whiteSpace: 'nowrap',\n }}\n >\n {leadingDropdownText}\n </span>\n <svg width={t.chevronSize} height={t.chevronSize} viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6L8 10L12 6\" stroke={grayNeutral.fgHigh} strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </div>\n ) : LeadingIconComponent ? (\n /* Leading icon in input → fg/high (#1B1D22) per Figma */\n <LeadingIconComponent\n size={t.iconSize}\n color={inputIconColor}\n strokeWidth={1.6}\n style={{ flexShrink: 0 }}\n />\n ) : null}\n\n {/* Text + accessories area */}\n <div\n style={{\n flex: '1 0 0',\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n height: '100%',\n minWidth: 0,\n ...(leadingDropdownText\n ? { borderLeft: `1px solid ${grayNeutral.borderLight}`, padding: `0 12px` }\n : {}),\n }}\n >\n {/* Placeholder / Value text */}\n <div\n style={{\n flex: '1 0 0',\n overflow: 'hidden',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: value ? valueColor : placeholderColor,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n display: 'block',\n width: '100%',\n }}\n >\n {value || placeholder}\n </span>\n </div>\n\n {/* Counter pill */}\n {counter && (\n <div\n style={{\n background: grayNeutral.bgLightgray,\n display: 'flex',\n gap: 2,\n alignItems: 'center',\n justifyContent: 'center',\n padding: t.counterPadding,\n borderRadius: t.counterRadius,\n flexShrink: 0,\n opacity: isDisabled ? 0.7 : 1,\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.counterFontSize,\n lineHeight: `${t.counterLineHeight}px`,\n color: grayNeutral.fgHigh,\n }}\n >\n {counter.value}\n </span>\n <span\n style={{\n ...baseFont,\n fontSize: t.counterFontSize,\n lineHeight: `${t.counterLineHeight}px`,\n color: grayNeutral.fgMid,\n }}\n >\n / {counter.max}\n </span>\n </div>\n )}\n\n {/* Unit text */}\n {unit && (\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: grayNeutral.fgHigh,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n maxWidth: 64,\n overflow: 'hidden',\n }}\n >\n {unit}\n </span>\n )}\n\n {/* Trailing icons */}\n {iconsToRender.length > 0 && (\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, flexShrink: 0 }}>\n {iconsToRender.map((ic, idx) => {\n const TrailingIcon = TRAILING_ICON_MAP[ic];\n return (\n <React.Fragment key={`${ic}-${idx}`}>\n {trailingIconSeparator && idx > 0 && (\n <div\n style={{\n width: 1,\n height: t.iconSize,\n background: grayNeutral.gray300,\n flexShrink: 0,\n alignSelf: 'center',\n }}\n />\n )}\n {/* Trailing icon → fg/high (#1B1D22) per Figma */}\n <TrailingIcon\n size={t.iconSize}\n color={inputIconColor}\n strokeWidth={1.6}\n style={{ flexShrink: 0 }}\n />\n </React.Fragment>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* ── Level 1: helper / error text ────────────────────────────────── */}\n {/*\n * No extra margin here — the outer helperGap (4px sm / 4px md / 6px lg)\n * from the flex container already provides the correct spacing from Figma.\n */}\n {showText && (\n <p\n style={{\n ...baseFont,\n margin: 0,\n fontSize: t.helperFontSize,\n lineHeight: `${t.helperLineHeight}px`,\n color: helperColor,\n width: '100%',\n }}\n >\n {showText}\n </p>\n )}\n </div>\n );\n};\n","// ─── Senestia Design System — Public API ─────────────────────────────────────\n//\n// import { Badge, InputField, tokens } from '@senestia/ui'\n//\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ── Components ────────────────────────────────────────────────────────────────\nexport { Badge } from './stories/Badge';\nexport { InputField } from './stories/InputField';\n\n// ── Component types ───────────────────────────────────────────────────────────\nexport type { BadgeProps, BadgeColor, BadgeSize, BadgeType } from './stories/Badge';\nexport type {\n InputFieldProps,\n InputFieldState,\n InputFieldSize,\n InputFieldTrailingIcon,\n InputFieldCounter,\n} from './stories/InputField';\n\n// ── Design Tokens ─────────────────────────────────────────────────────────────\nexport {\n // Colors\n grayNeutral,\n status,\n ciPrimary,\n oePrimary,\n interactive,\n // Spacing\n padding,\n radius,\n // Typography\n font,\n} from './stories/tokens';\n\n// ── Tokens namespace (for tree-shaking friendly usage) ────────────────────────\nimport * as _tokens from './stories/tokens';\nexport const tokens = _tokens;\n"],"mappings":";;;;;;;;;;;GAIM,IAAO,uBAuCP,IAGF;CACF,MAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,SAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,OAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,SAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,SAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,cAAc;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACnF,MAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,QAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,QAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,MAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,QAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CACjF,aAAY;EAAE,IAAI;EAAW,QAAQ;EAAW,MAAM;EAAW,KAAK;EAAW;CAClF,EAIK,IAcF;CACF,IAAI;EACF,UAAU;EAAG,UAAU;EACvB,eAAe;GAAE,MAAM;GAAG,OAAO;GAAG;EACpC,aAAa;GAAE,MAAM;GAAG,OAAO;GAAG;EAClC,aAAa;EACb,UAAU;EAAI,YAAY;EAC1B,SAAS;EAAG,UAAU;EAAI,WAAW;EACtC;CACD,IAAI;EACF,UAAU;EAAG,UAAU;EACvB,eAAe;GAAE,MAAM;GAAG,OAAO;GAAG;EACpC,aAAa;GAAE,MAAM;GAAG,OAAO;GAAG;EAClC,aAAa;EACb,UAAU;EAAI,YAAY;EAC1B,SAAS;EAAG,UAAU;EAAI,WAAW;EACtC;CACD,IAAI;EACF,UAAU;EAAI,UAAU;EACxB,eAAe;GAAE,MAAM;GAAI,OAAO;GAAG;EACrC,aAAa;GAAE,MAAM;GAAG,OAAO;GAAI;EACnC,aAAa;EACb,UAAU;EAAI,YAAY;EAC1B,SAAS;EAAG,UAAU;EAAI,WAAW;EACtC;CACF,EAIY,KAA+B,EAC1C,WAAQ,SACR,WAAQ,QACR,UAAO,MACP,UAAO,QACP,MAAM,GACN,iBACI;CACJ,IAAM,IAAI,EAAa,IACjB,IAAI,EAAY,IAGhB,IAAmC;EACvC,SAAS;EACT,YAAY;EACZ,iBAAiB,EAAE;EACnB,QAAQ,aAAa,EAAE;EACvB,cAAc;EACd,WAAW;EACX,OAAO;EACP,YAAY;EACb,EAGK,IAAiC;EACrC,UAAU,EAAE;EACZ,YAAY,GAAG,EAAE,WAAW;EAC5B,YAAY;EACZ,OAAO,EAAE;EACT,YAAY;EACZ,YAAY;EACZ,QAAQ;EACT;AAGD,KAAI,MAAS,OACX,QACE,kBAAC,QAAD;EACE,OAAO;GACL,GAAG;GACH,SAAS,GAAG,EAAE,SAAS,KAAK,EAAE,SAAS;GACxC;YAED,kBAAC,QAAD;GAAM,OAAO;aAAY;GAAa,CAAA;EACjC,CAAA;AAKX,KAAI,MAAS,aACX,QACE,kBAAC,QAAD;EACE,OAAO;GACL,GAAG;GACH,KAAK;GACL,YAAY,EAAE;GACd,eAAe,EAAE;GACjB,aAAa,EAAE,YAAY;GAC3B,cAAc,EAAE,YAAY;GAC7B;YARH,CAWE,kBAAC,QAAD,EACE,OAAO;GACL,SAAS;GACT,OAAO,EAAE;GACT,QAAQ,EAAE;GACV,cAAc;GACd,iBAAiB,EAAE;GACnB,YAAY;GACb,EACD,CAAA,EACF,kBAAC,QAAD;GAAM,OAAO;aAAY;GAAa,CAAA,CACjC;;AAKX,KAAI,MAAS,WACX,QACE,kBAAC,QAAD;EACE,OAAO;GACL,GAAG;GACH,KAAK;GACL,YAAY,EAAE;GACd,eAAe,EAAE;GACjB,aAAa,EAAE,cAAc;GAC7B,cAAc,EAAE,cAAc;GAC/B;YARH,CAUE,kBAAC,QAAD;GAAM,OAAO;aAAY;GAAa,CAAA,EACtC,kBAAC,UAAD;GACE,SAAS;GACT,OAAO;IACL,SAAS;IACT,YAAY;IACZ,gBAAgB;IAChB,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,cAAc;IACd,QAAQ;IACR,OAAO,EAAE;IACT,YAAY;IACZ,YAAY;IACb;GACD,cAAW;aAEX,kBAAC,GAAD;IAAG,MAAM,EAAE;IAAW,aAAa;IAAO,CAAA;GACnC,CAAA,CACJ;;AAKX,KAAI,MAAS,cAAc;EACzB,IAAM,IAAW;AACjB,SACE,kBAAC,QAAD;GACE,OAAO;IACL,GAAG;IACH,SAAS,EAAE;IACZ;aAEA,IACC,kBAAC,GAAD;IAAU,MAAM,EAAE;IAAU,OAAO,EAAE;IAAK,aAAa;IAAK,CAAA,GAG5D,kBAAC,QAAD,EACE,OAAO;IACL,SAAS;IACT,OAAO,EAAE;IACT,QAAQ,EAAE;IACV,cAAc;IACd,iBAAiB,EAAE;IACpB,EACD,CAAA;GAEC,CAAA;;AAIX,QAAO;;;;;;;;;;IC7OI,IAAc;CAEzB,QAAQ;CAER,OAAO;CAEP,OAAO;CAGP,SAAS;CAET,aAAa;CAEb,YAAY;CAGZ,eAAe;CAEf,aAAa;CAEb,gBAAgB;CAGhB,SAAS;CAET,YAAY;CAEZ,kBAAkB;CACnB,EAIY,IAAS;CAEpB,OAAO;CAEP,SAAS;CAET,SAAS;CACV,EAIY,IAAY;CACvB,OAAa;CACb,QAAa;CACb,OAAa;CACb,OAAa;CACb,QAAa;CACb,WAAa;CACb,YAAa;CACd,EAIY,IAAY;CACvB,OAAa;CACb,QAAa;CACb,UAAa;CACb,OAAa;CACb,OAAa;CACb,QAAa;CACb,cAAa;CACb,WAAa;CACb,WAAa;CAEb,MAAa;CAEb,UAAa;CACd,EAIY,IAAc;CAEzB,cAAgB,EAAU;CAE1B,aAAgB;CAEhB,WAAgB;CAEhB,eAAgB,EAAO;CACxB,EAIY,IAAU;CACrB,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACV,EAIY,IAAS;CACpB,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,QAAS;CACT,SAAS;CACV,EAIY,IAAO,uBChDd,IAAa;CACjB,IAAI;EACF,aAAa;EACb,eAAe;EAAI,iBAAiB;EACpC,eAAe;EAAI,iBAAiB;EACpC,gBAAgB;EAAI,kBAAkB;EACtC,UAAU;EACV,UAAU;EACV,eAAe;EACf,UAAU;EACV,WAAW;EACX,WAAW;EAAG,WAAW;EAAG,WAAW;EACvC,aAAa;EACb,gBAAgB;EAChB,eAAe;EACf,iBAAiB;EAAI,mBAAmB;EACxC,gBAAgB;EAAI,gBAAgB;EACrC;CACD,IAAI;EACF,aAAa;EACb,eAAe;EAAI,iBAAiB;EACpC,eAAe;EAAI,iBAAiB;EACpC,gBAAgB;EAAI,kBAAkB;EACtC,UAAU;EACV,UAAU;EACV,eAAe;EACf,UAAU;EACV,WAAW;EACX,WAAW;EAAI,WAAW;EAAG,WAAW;EACxC,aAAa;EACb,gBAAgB;EAChB,eAAe;EACf,iBAAiB;EAAI,mBAAmB;EACxC,gBAAgB;EAAI,gBAAgB;EACrC;CACD,IAAI;EACF,aAAa;EACb,eAAe;EAAI,iBAAiB;EACpC,eAAe;EAAI,iBAAiB;EACpC,gBAAgB;EAAI,kBAAkB;EACtC,UAAU;EACV,UAAU;EACV,eAAe;EACf,UAAU;EACV,WAAW;EACX,WAAW;EAAI,WAAW;EAAG,WAAW;EACxC,aAAa;EACb,gBAAgB;EAChB,eAAe;EACf,iBAAiB;EAAI,mBAAmB;EACxC,gBAAgB;EAAI,gBAAgB;EACrC;CACF,EAIK,IAAiB,aAAa,EAAY,aAE1C,KAAiB,MAAuC;CAC5D,IAAM,IAAI,KAAS;AAQnB,QAAO;EAAE;EAAG,WAPO,EAAE,SAAS,UAAU;EAOjB,SANJ,EAAE,SAAS,QAAQ;EAMN,UALb,MAAM,YAAY,MAAM,oBAAoB,EAAE,SAAS,SAAS;EAKzC,YAJvB,MAAM;EAI6B,YAHnC,MAAM;EAGyC,UAF/C,EAAE,SAAS,SAAS;EAEqC,iBADpD,MAAM;EAC+D;GAKzF,IAAoB;CACxB,OAAU;CACV,QAAU;CACV,UAAU;CACX,EAIY,KAAc,EACzB,UACA,cAAW,IACX,gBACA,iBAAc,eACd,UACA,UAAU,GACV,eACA,cACA,WAAQ,QACR,UAAO,MACP,wBACA,gBACA,YACA,SACA,iBACA,kBACA,2BAAwB,SACH;CACrB,IAAM,EAAE,cAAW,YAAS,aAAU,eAAY,eAAY,uBAC5D,EAAc,EAAM,EAEhB,IAAI,EAAW,IAGf,IAAc,IAChB,EAAY,gBACZ,KAAY,IACV,EAAY,eACZ,IACE,EAAY,cACZ,EAAY,eAEd,IAAa,IACf,EAAY,aACZ,IACE,EAAY,cACZ,EAAY,SAGZ,IAAa,IAAa,EAAY,QAAQ,EAAY,OAG1D,IAAmB,EAAY,OAG/B,IAAa,IAAa,EAAY,QAAQ,EAAY,QAI1D,IAAiB,IAAa,EAAY,QAAQ,EAAY,QAE9D,IAAiB,IAAa,EAAY,QAAQ,EAAY,OAE9D,IAAc,IAAY,EAAO,QAAQ,EAAY;AAG3D,KAAI,EACF,QACE,kBAAC,OAAD;EAAK,OAAO;GAAE,OAAO;GAAK,SAAS;GAAQ,eAAe;GAAU,KAAK,EAAE;GAAU;YAArF,CACE,kBAAC,OAAD,EAAK,OAAO;GAAE,QAAQ,EAAE;GAAgB,YAAY,EAAY;GAAY,cAAc;GAAG,EAAI,CAAA,EACjG,kBAAC,OAAD,EAAK,OAAO;GAAE,QAAQ,EAAE;GAAgB,YAAY,EAAY;GAAY,QAAQ,aAAa,EAAY;GAAc,cAAc;GAAI,EAAI,CAAA,CAC7I;;CAMV,IAAM,IACJ,MAAgB,KACZ,IACA,KAEE,MAGF,IACJ,GAAe,SAAS,IAAgB,IAAe,CAAC,EAAa,GAAG,EAAE,EAGtE,IAAW,IAAY,IAAY,GAGnC,IAAgC;EAAE,YAAY;EAAM,YAAY;EAAK;AAE3E,QAME,kBAAC,OAAD;EAAK,OAAO;GAAE,OAAO;GAAK,SAAS;GAAQ,eAAe;GAAU,KAAK,EAAE;GAAW;YAAtF,CAGE,kBAAC,OAAD;GAAK,OAAO;IAAE,SAAS;IAAQ,eAAe;IAAU,KAAK,EAAE;IAAU,OAAO;IAAQ;aAAxF,CAGE,kBAAC,OAAD;IAAK,OAAO;KAAE,SAAS;KAAQ,YAAY;KAAU,KAAK;KAAG,OAAO;KAAQ;cAA5E;KAEE,kBAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,MAAM;OAAS,YAAY;OAAU,KAAK,EAAE,kBAAkB,KAAK,IAAI;OAAG,UAAU;OAAG;gBAAtH,CACE,kBAAC,QAAD;OACE,OAAO;QACL,GAAG;QACH,UAAU,EAAE;QACZ,YAAY,GAAG,EAAE,gBAAgB;QACjC,OAAO;QACP,YAAY;QACZ,UAAU;QACV,cAAc;QACf;iBAEA;OACI,CAAA,EAEP,kBAAC,GAAD;OACE,MAAM,EAAE;OACR,OAAO;OACP,aAAa;OACb,OAAO,EAAE,YAAY,GAAG;OACxB,CAAA,CACE;;KAGL,KACC,kBAAC,QAAD;MACE,OAAO;OACL,GAAG;OACH,UAAU,EAAE;OACZ,YAAY,GAAG,EAAE,gBAAgB;OACjC,OAAO;OACP,YAAY;OACZ,YAAY;OACb;gBAEA;MACI,CAAA;KAER,KACC,kBAAC,QAAD;MAAM,OAAO;OAAE,OAAO,EAAO;OAAO,YAAY;OAAK,YAAY;OAAG;gBAAE;MAAQ,CAAA;KAE5E;OAGN,kBAAC,OAAD;IACE,OAAO;KACL;KACA,QAAQ,aAAa;KACrB,QAAQ,EAAE;KACV,OAAO;KACP,cAAc;KACd,SAAS;KACT,YAAY,IAAsB,YAAY;KAC9C,GAAI,IAAsB,EAAE,GAAG;MAAE,KAAK;MAAG,SAAS,KAAK,EAAE,SAAS;MAAK;KACvE,UAAU;KACV,WAAW,KAAY,IAAkB,IAAiB;KAC1D,SAAS,IAAa,KAAM;KAC5B,WAAW;KACZ;cAdH,CAiBG,IACC,kBAAC,OAAD;KACE,OAAO;MACL,SAAS;MACT,YAAY;MACZ,KAAK;MACL,YAAY,EAAY;MACxB,SAAS,GAAG,EAAE,UAAU,KAAK,EAAE,UAAU,KAAK,EAAE,UAAU,KAAK,EAAE,UAAU;MAC3E,YAAY;MACb;eARH,CAUE,kBAAC,QAAD;MACE,OAAO;OACL,GAAG;OACH,UAAU,EAAE;OACZ,YAAY,GAAG,EAAE,gBAAgB;OACjC,OAAO,EAAY;OACnB,YAAY;OACb;gBAEA;MACI,CAAA,EACP,kBAAC,OAAD;MAAK,OAAO,EAAE;MAAa,QAAQ,EAAE;MAAa,SAAQ;MAAY,MAAK;gBACzE,kBAAC,QAAD;OAAM,GAAE;OAAiB,QAAQ,EAAY;OAAQ,aAAY;OAAM,eAAc;OAAQ,gBAAe;OAAU,CAAA;MAClH,CAAA,CACF;SACJ,IAEF,kBAAC,GAAD;KACE,MAAM,EAAE;KACR,OAAO;KACP,aAAa;KACb,OAAO,EAAE,YAAY,GAAG;KACxB,CAAA,GACA,MAGJ,kBAAC,OAAD;KACE,OAAO;MACL,MAAM;MACN,SAAS;MACT,YAAY;MACZ,KAAK;MACL,QAAQ;MACR,UAAU;MACV,GAAI,IACA;OAAE,YAAY,aAAa,EAAY;OAAe,SAAS;OAAU,GACzE,EAAE;MACP;eAXH;MAcE,kBAAC,OAAD;OACE,OAAO;QACL,MAAM;QACN,UAAU;QACV,SAAS;QACT,YAAY;QACb;iBAED,kBAAC,QAAD;QACE,OAAO;SACL,GAAG;SACH,UAAU,EAAE;SACZ,YAAY,GAAG,EAAE,gBAAgB;SACjC,OAAO,IAAQ,IAAa;SAC5B,UAAU;SACV,cAAc;SACd,YAAY;SACZ,SAAS;SACT,OAAO;SACR;kBAEA,KAAS;QACL,CAAA;OACH,CAAA;MAGL,KACC,kBAAC,OAAD;OACE,OAAO;QACL,YAAY,EAAY;QACxB,SAAS;QACT,KAAK;QACL,YAAY;QACZ,gBAAgB;QAChB,SAAS,EAAE;QACX,cAAc,EAAE;QAChB,YAAY;QACZ,SAAS,IAAa,KAAM;QAC7B;iBAXH,CAaE,kBAAC,QAAD;QACE,OAAO;SACL,GAAG;SACH,UAAU,EAAE;SACZ,YAAY,GAAG,EAAE,kBAAkB;SACnC,OAAO,EAAY;SACpB;kBAEA,EAAQ;QACJ,CAAA,EACP,kBAAC,QAAD;QACE,OAAO;SACL,GAAG;SACH,UAAU,EAAE;SACZ,YAAY,GAAG,EAAE,kBAAkB;SACnC,OAAO,EAAY;SACpB;kBANH,CAOC,MACI,EAAQ,IACN;UACH;;MAIP,KACC,kBAAC,QAAD;OACE,OAAO;QACL,GAAG;QACH,UAAU,EAAE;QACZ,YAAY,GAAG,EAAE,gBAAgB;QACjC,OAAO,EAAY;QACnB,YAAY;QACZ,YAAY;QACZ,UAAU;QACV,UAAU;QACX;iBAEA;OACI,CAAA;MAIR,EAAc,SAAS,KACtB,kBAAC,OAAD;OAAK,OAAO;QAAE,SAAS;QAAQ,YAAY;QAAU,KAAK;QAAG,YAAY;QAAG;iBACzE,EAAc,KAAK,GAAI,MAAQ;QAC9B,IAAM,IAAe,EAAkB;AACvC,eACE,kBAAC,EAAM,UAAP,EAAA,UAAA,CACG,KAAyB,IAAM,KAC9B,kBAAC,OAAD,EACE,OAAO;SACL,OAAO;SACP,QAAQ,EAAE;SACV,YAAY,EAAY;SACxB,YAAY;SACZ,WAAW;SACZ,EACD,CAAA,EAGJ,kBAAC,GAAD;SACE,MAAM,EAAE;SACR,OAAO;SACP,aAAa;SACb,OAAO,EAAE,YAAY,GAAG;SACxB,CAAA,CACa,EAAA,EAnBI,GAAG,EAAG,GAAG,IAmBb;SAEnB;OACE,CAAA;MAEJ;OACF;MACF;MAOL,KACC,kBAAC,KAAD;GACE,OAAO;IACL,GAAG;IACH,QAAQ;IACR,UAAU,EAAE;IACZ,YAAY,GAAG,EAAE,iBAAiB;IAClC,OAAO;IACP,OAAO;IACR;aAEA;GACC,CAAA,CAEF;;GC1dG,IAAS"}
|
|
1
|
+
{"version":3,"file":"senestia-ui.es.js","names":[],"sources":["../src/stories/Badge.tsx","../src/stories/tokens.ts","../src/stories/InputField.tsx","../src/index.ts"],"sourcesContent":["import React from 'react';\nimport { X } from 'lucide-react';\n\n// ─── Design System Font ──────────────────────────────────────────────────────\nconst font = 'Sarabun, sans-serif';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type BadgeColor =\n | 'Gray'\n | 'Primary'\n | 'Error'\n | 'Warning'\n | 'Success'\n | 'Blue light'\n | 'Blue'\n | 'Indigo'\n | 'Purple'\n | 'Pink'\n | 'Orange'\n | 'Gray blue';\n\nexport type BadgeSize = 'sm' | 'md' | 'lg';\n\nexport type BadgeType = 'Idle' | 'Status Dot' | 'Closable' | 'Pill color';\n\nexport interface BadgeProps {\n /** Badge label text */\n label?: string;\n /** Color variant */\n color?: BadgeColor;\n /** Size variant */\n size?: BadgeSize;\n /** Type / style variant */\n type?: BadgeType;\n /** Icon to render inside Pill color type (Lucide icon component) */\n icon?: React.ElementType;\n /** Called when close button is clicked (Closable type) */\n onClose?: () => void;\n}\n\n// ─── Color Tokens ────────────────────────────────────────────────────────────\n\nconst COLOR_TOKENS: Record<\n BadgeColor,\n { bg: string; border: string; text: string; dot: string }\n> = {\n Gray: { bg: '#f9fafb', border: '#eaecf0', text: '#06080b', dot: '#667085' },\n Primary: { bg: '#f4f6f9', border: '#e6ebf2', text: '#1e2b3b', dot: '#6c8fbe' },\n Error: { bg: '#fef0ef', border: '#fbd2d0', text: '#cc1a11', dot: '#f04438' },\n Warning: { bg: '#fff9ee', border: '#ffedcc', text: '#db8f02', dot: '#f79009' },\n Success: { bg: '#f0fdfa', border: '#d2f9f1', text: '#15a686', dot: '#12b76a' },\n 'Blue light': { bg: '#f0f9ff', border: '#b9e6fe', text: '#026aa2', dot: '#0ba5ec' },\n Blue: { bg: '#eff8ff', border: '#b2ddff', text: '#175cd3', dot: '#2e90fa' },\n Indigo: { bg: '#eef4ff', border: '#c7d7fe', text: '#3538cd', dot: '#6172f3' },\n Purple: { bg: '#f4f3ff', border: '#d9d6fe', text: '#5925dc', dot: '#7a5af8' },\n Pink: { bg: '#fef6fb', border: '#fce7f6', text: '#c11574', dot: '#ee46bc' },\n Orange: { bg: '#fef6ee', border: '#ffd6ae', text: '#b93815', dot: '#ef6820' },\n 'Gray blue':{ bg: '#f8f9fc', border: '#d5d9eb', text: '#363f72', dot: '#717bbc' },\n};\n\n// ─── Size Tokens ─────────────────────────────────────────────────────────────\n\nconst SIZE_TOKENS: Record<\n BadgeSize,\n {\n paddingX: number;\n paddingY: number;\n paddingXClose: { left: number; right: number };\n paddingXDot: { left: number; right: number };\n paddingPill: number;\n fontSize: number;\n lineHeight: number;\n dotSize: number;\n iconSize: number;\n closeSize: number;\n }\n> = {\n sm: {\n paddingX: 8, paddingY: 2,\n paddingXClose: { left: 8, right: 4 },\n paddingXDot: { left: 6, right: 8 },\n paddingPill: 5,\n fontSize: 12, lineHeight: 18,\n dotSize: 6, iconSize: 12, closeSize: 12,\n },\n md: {\n paddingX: 8, paddingY: 2,\n paddingXClose: { left: 8, right: 4 },\n paddingXDot: { left: 6, right: 8 },\n paddingPill: 6,\n fontSize: 14, lineHeight: 20,\n dotSize: 6, iconSize: 14, closeSize: 14,\n },\n lg: {\n paddingX: 12, paddingY: 4,\n paddingXClose: { left: 12, right: 6 },\n paddingXDot: { left: 8, right: 12 },\n paddingPill: 8,\n fontSize: 14, lineHeight: 20,\n dotSize: 8, iconSize: 16, closeSize: 16,\n },\n};\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport const Badge: React.FC<BadgeProps> = ({\n label = 'Label',\n color = 'Gray',\n size = 'sm',\n type = 'Idle',\n icon: IconComponent,\n onClose,\n}) => {\n const c = COLOR_TOKENS[color];\n const s = SIZE_TOKENS[size];\n\n // ── Shared wrapper style ──────────────────────────────────────────────────\n const baseWrapper: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n backgroundColor: c.bg,\n border: `1px solid ${c.border}`,\n borderRadius: 16,\n boxSizing: 'border-box',\n width: 'fit-content',\n fontFamily: font,\n };\n\n // ── Text style ────────────────────────────────────────────────────────────\n const textStyle: React.CSSProperties = {\n fontSize: s.fontSize,\n lineHeight: `${s.lineHeight}px`,\n fontWeight: 500,\n color: c.text,\n whiteSpace: 'nowrap',\n fontFamily: font,\n margin: 0,\n };\n\n // ── Idle ─────────────────────────────────────────────────────────────────\n if (type === 'Idle') {\n return (\n <span\n style={{\n ...baseWrapper,\n padding: `${s.paddingY}px ${s.paddingX}px`,\n }}\n >\n <span style={textStyle}>{label}</span>\n </span>\n );\n }\n\n // ── Status Dot ────────────────────────────────────────────────────────────\n if (type === 'Status Dot') {\n return (\n <span\n style={{\n ...baseWrapper,\n gap: 4,\n paddingTop: s.paddingY,\n paddingBottom: s.paddingY,\n paddingLeft: s.paddingXDot.left,\n paddingRight: s.paddingXDot.right,\n }}\n >\n {/* Dot */}\n <span\n style={{\n display: 'inline-block',\n width: s.dotSize,\n height: s.dotSize,\n borderRadius: '50%',\n backgroundColor: c.dot,\n flexShrink: 0,\n }}\n />\n <span style={textStyle}>{label}</span>\n </span>\n );\n }\n\n // ── Closable ──────────────────────────────────────────────────────────────\n if (type === 'Closable') {\n return (\n <span\n style={{\n ...baseWrapper,\n gap: 2,\n paddingTop: s.paddingY,\n paddingBottom: s.paddingY,\n paddingLeft: s.paddingXClose.left,\n paddingRight: s.paddingXClose.right,\n }}\n >\n <span style={textStyle}>{label}</span>\n <button\n onClick={onClose}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'none',\n border: 'none',\n padding: 2,\n borderRadius: 3,\n cursor: 'pointer',\n color: c.text,\n flexShrink: 0,\n lineHeight: 1,\n }}\n aria-label=\"Remove\"\n >\n <X size={s.closeSize} strokeWidth={2.5} />\n </button>\n </span>\n );\n }\n\n // ── Pill color (icon only) ────────────────────────────────────────────────\n if (type === 'Pill color') {\n const PillIcon = IconComponent;\n return (\n <span\n style={{\n ...baseWrapper,\n padding: s.paddingPill,\n }}\n >\n {PillIcon ? (\n <PillIcon size={s.iconSize} color={c.dot} strokeWidth={2} />\n ) : (\n // Default: colored circle dot\n <span\n style={{\n display: 'inline-block',\n width: s.iconSize,\n height: s.iconSize,\n borderRadius: '50%',\n backgroundColor: c.dot,\n }}\n />\n )}\n </span>\n );\n }\n\n return null;\n};\n","/**\n * Senestia Design System — Semantic Color Tokens\n *\n * ┌─────────────────────────────────────────────────────────────┐\n * │ Source: Figma DS-01 · Foundation → Semantic Color │\n * │ Use these tokens in components instead of raw hex values. │\n * └─────────────────────────────────────────────────────────────┘\n */\n\n// ─── Gray-Neutral ─────────────────────────────────────────────────────────────\n\nexport const grayNeutral = {\n /** Semantic/Gray-Neutral/fg/high — primary text, dark icons */\n fgHigh: '#1B1D22',\n /** Semantic/Gray-Neutral/fg/mid-on-white — label text, helper text, secondary icons */\n fgMid: '#6A6E83',\n /** Semantic/Gray-Neutral/fg/low-on-white — placeholder, disabled text */\n fgLow: '#9A9DAD',\n\n /** Semantic/Gray-Neutral/bg/white */\n bgWhite: '#FFFFFF',\n /** Semantic/Gray-Neutral/bg/lightgray — counter pill, subtle backgrounds */\n bgLightgray: '#F8F8F9',\n /** Semantic/Gray-Neutral/bg/disabled */\n bgDisabled: '#F3F4F6',\n\n /** Semantic/Gray-Neutral/border/midgray — default input border */\n borderMidgray: '#CFD1D9',\n /** Semantic/Gray-Neutral/border/light — dividers, card borders */\n borderLight: '#EBECEF',\n /** Disabled border (checkbox, input) */\n borderDisabled: '#E5EAF1',\n\n /** Gray/300 — icon separators */\n gray300: '#D0D5DD',\n /** Skeleton loading shimmer */\n bgSkeleton: '#EEF0F3',\n /** Strong disabled background (checkbox) */\n bgDisabledStrong: '#EBECEF',\n} as const;\n\n// ─── Status ───────────────────────────────────────────────────────────────────\n\nexport const status = {\n /** Error / invalid state */\n error: '#DB1439',\n /** Warning */\n warning: '#DB8F02',\n /** Success */\n success: '#15A686',\n} as const;\n\n// ─── CI Primary (Senestia brand purple) ───────────────────────────────────────\n\nexport const ciPrimary = {\n fgLow: '#C4B3F6',\n fgHigh: '#802CEB',\n bgLow: '#D4C9F6',\n bgMid: '#802CEB',\n bgHigh: '#5A1DA9',\n borderMid: '#996CF3',\n borderHigh: '#802CEB',\n} as const;\n\n// ─── OE Theme (OE brand blue) ─────────────────────────────────────────────────\n\nexport const oePrimary = {\n fgLow: '#5273A1',\n fgHigh: '#3A5274',\n bgLowest: '#EFF2F6', // selected item background in pickers\n bgLow: '#6E90BF',\n bgMid: '#5273A1',\n bgHigh: '#3A5274',\n borderLowest:'#C6D2E3', // focused item border\n borderLow: '#9CB3D2',\n borderMid: '#5273A1',\n /** Primary/300 — supporting/helper text on blue-tinted UI */\n p300: '#809BBF',\n /** Indigo/300 — \"Set to now\" link color */\n linkBlue: '#3C5BD5',\n} as const;\n\n// ─── Interactive states ───────────────────────────────────────────────────────\n\nexport const interactive = {\n /** Active / focused border */\n activeBorder: oePrimary.fgLow, // #5273A1\n /** Hover border */\n hoverBorder: '#3B82F6',\n /** Focus ring shadow */\n focusRing: '#D7DFEA',\n /** Invalid border */\n invalidBorder: status.error,\n} as const;\n\n// ─── Padding tokens (PD) ─────────────────────────────────────────────────────\n\nexport const padding = {\n 'PD-0': 0,\n 'PD-1': 1,\n 'PD-2': 2,\n 'PD-3': 4,\n 'PD-4': 6,\n 'PD-5': 8,\n 'PD-6': 12,\n 'PD-7': 16,\n 'PD-8': 24,\n 'PD-9': 32,\n 'PD-10': 40,\n 'PD-11': 48,\n 'PD-12': 56,\n 'PD-13': 64,\n 'PD-14': 72,\n 'PD-15': 80,\n} as const;\n\n// ─── Corner Radius tokens (CR) ───────────────────────────────────────────────\n\nexport const radius = {\n 'CR-0': 0,\n 'CR-1': 2,\n 'CR-2': 4,\n 'CR-3': 8,\n 'CR-4': 12,\n 'CR-5': 16,\n 'CR-6': 20,\n 'CR-7': 24,\n 'CR-8': 32,\n 'CR-9': 48,\n 'CR-10': 100,\n} as const;\n\n// ─── Typography ───────────────────────────────────────────────────────────────\n\nexport const font = 'Sarabun, sans-serif';\n","import React from 'react';\nimport { Circle, Info, XCircle, Search, Eye } from 'lucide-react';\nimport { grayNeutral, status, interactive, font } from './tokens';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type InputFieldState =\n | 'Idle'\n | 'Idle hover'\n | 'Active'\n | 'Idle invalid'\n | 'Idle invalid hover'\n | 'Idle invalid active'\n | 'Filled'\n | 'Filled hover'\n | 'Filled active'\n | 'Filled invalid'\n | 'Filled invalid hover'\n | 'Filled invalid active'\n | 'Disable'\n | 'Keyboard focus'\n | 'Skeleton';\n\nexport type InputFieldSize = 'sm' | 'md' | 'lg';\n\nexport type InputFieldTrailingIcon = 'clear' | 'password' | 'search';\n\nexport type InputFieldCounter = {\n value: number;\n max: number;\n};\n\nexport interface InputFieldProps {\n /** Label text displayed above the input */\n label: string;\n /** Show required asterisk (*) */\n required?: boolean;\n /** Remark text next to label e.g. \"(optional)\" */\n labelRemark?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Current value */\n value?: string;\n /** Called when value changes */\n onChange?: (value: string) => void;\n /** Helper text below the input (hidden when invalid) */\n helperText?: string;\n /** Error message below the input (shown when invalid state) */\n errorText?: string;\n /** Visual state from Figma */\n state?: InputFieldState;\n /** Input size — affects height, font, and padding */\n size?: InputFieldSize;\n /** Leading dropdown prefix text */\n leadingDropdownText?: string;\n /**\n * Leading icon inside the input (left side).\n * - `true` → default Circle icon\n * - `React.ElementType` → custom Lucide icon\n * - `false/undefined` → no icon\n */\n leadingIcon?: React.ElementType | boolean;\n /** Counter pill e.g. `{ value: 0, max: 20 }` */\n counter?: InputFieldCounter;\n /** Unit text inside the input */\n unit?: string;\n /** Single trailing icon */\n trailingIcon?: InputFieldTrailingIcon;\n /** Multiple trailing icons (overrides trailingIcon) */\n trailingIcons?: InputFieldTrailingIcon[];\n /** Show separator between trailing icons */\n trailingIconSeparator?: boolean;\n}\n\n// ─── Design tokens (from Figma) ──────────────────────────────────────────────\n\n/**\n * Size tokens — matched to Figma nodes:\n * sm (Sm-32): label C5 12/18 · input C4 14/20 · helper C5 12/18\n * md (Md-40): label C4 14/20 · input C3 16/24 · helper C4 14/20\n * lg (Lg-48): label C3 16/24 · input C3 16/24 · helper C4 14/20\n *\n * Spacing (per Figma sm node — gap-4 between all elements):\n * labelGap = gap between label row and input box\n * helperGap = gap between input box and helper/error text\n */\nconst sizeTokens = {\n sm: {\n inputHeight: 32,\n labelFontSize: 12, labelLineHeight: 18,\n inputFontSize: 14, inputLineHeight: 20,\n helperFontSize: 12, helperLineHeight: 18,\n paddingX: 12,\n iconSize: 16,\n labelIconSize: 12,\n labelGap: 4, // label row → input\n helperGap: 4, // input → helper text\n leadingPl: 8, leadingPr: 4, leadingPy: 6,\n chevronSize: 14,\n counterPadding: '1px 4px',\n counterRadius: 4,\n counterFontSize: 12, counterLineHeight: 18,\n skeletonLabelH: 18, skeletonInputH: 32,\n },\n md: {\n inputHeight: 40,\n labelFontSize: 14, labelLineHeight: 20,\n inputFontSize: 16, inputLineHeight: 24,\n helperFontSize: 14, helperLineHeight: 20,\n paddingX: 16,\n iconSize: 20,\n labelIconSize: 14,\n labelGap: 6, // label row → input\n helperGap: 4, // input → helper text\n leadingPl: 12, leadingPr: 8, leadingPy: 8,\n chevronSize: 16,\n counterPadding: '2px 8px',\n counterRadius: 8,\n counterFontSize: 14, counterLineHeight: 20,\n skeletonLabelH: 20, skeletonInputH: 40,\n },\n lg: {\n inputHeight: 48,\n labelFontSize: 16, labelLineHeight: 24,\n inputFontSize: 16, inputLineHeight: 24,\n helperFontSize: 14, helperLineHeight: 20,\n paddingX: 16,\n iconSize: 20,\n labelIconSize: 16,\n labelGap: 8, // label row → input\n helperGap: 6, // input → helper text\n leadingPl: 16, leadingPr: 8, leadingPy: 12,\n chevronSize: 16,\n counterPadding: '2px 8px',\n counterRadius: 8,\n counterFontSize: 14, counterLineHeight: 20,\n skeletonLabelH: 24, skeletonInputH: 48,\n },\n} as const;\n\n// ─── State helpers ────────────────────────────────────────────────────────────\n\nconst focusRingStyle = `0 0 0 2px ${interactive.focusRing}`;\n\nconst getStateFlags = (state: InputFieldState | undefined) => {\n const s = state ?? 'Idle';\n const isInvalid = s.includes('invalid');\n const isHover = s.includes('hover');\n const isActive = s === 'Active' || s === 'Keyboard focus' || s.endsWith('active');\n const isDisabled = s === 'Disable';\n const isSkeleton = s === 'Skeleton';\n const isFilled = s.includes('Filled');\n const isKeyboardFocus = s === 'Keyboard focus';\n return { s, isInvalid, isHover, isActive, isDisabled, isSkeleton, isFilled, isKeyboardFocus };\n};\n\n// ─── Trailing icon map → Lucide ───────────────────────────────────────────────\n\nconst TRAILING_ICON_MAP = {\n clear: XCircle,\n search: Search,\n password: Eye,\n} as const;\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport const InputField = ({\n label,\n required = false,\n labelRemark,\n placeholder = 'Placeholder',\n value,\n onChange: _onChange,\n helperText,\n errorText,\n state = 'Idle',\n size = 'md',\n leadingDropdownText,\n leadingIcon,\n counter,\n unit,\n trailingIcon,\n trailingIcons,\n trailingIconSeparator = false,\n}: InputFieldProps) => {\n const { isInvalid, isHover, isActive, isDisabled, isSkeleton, isKeyboardFocus } =\n getStateFlags(state);\n\n const t = sizeTokens[size];\n\n // ── Colors — mapped to Semantic/Gray-Neutral tokens ─────────────────────\n const borderColor = isInvalid\n ? interactive.invalidBorder // status.error #DB1439\n : isActive || isKeyboardFocus\n ? interactive.activeBorder // oePrimary.fgLow #5273A1\n : isHover\n ? interactive.hoverBorder // #3B82F6\n : grayNeutral.borderMidgray; // #CFD1D9\n\n const background = isDisabled\n ? grayNeutral.bgDisabled // #F3F4F6\n : isHover\n ? grayNeutral.bgLightgray // #F8F8F9\n : grayNeutral.bgWhite; // #FFFFFF\n\n // Label text → fg/mid-on-white (disabled → fg/low)\n const labelColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgMid;\n\n // Typed value → fg/high (disabled → fg/low)\n const valueColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgHigh; // #1B1D22\n\n // ── Icon colors (Figma: Semantic/Gray-Neutral/fg/high for input icons) ───\n // Input leading/trailing icons → fg/high (#1B1D22)\n const inputIconColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgHigh;\n // Label info icon → fg/mid (same as label text, #6A6E83)\n const labelIconColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgMid;\n\n const helperColor = isInvalid ? status.error : grayNeutral.fgMid; // #6A6E83\n\n // ── Skeleton ─────────────────────────────────────────────────────────────\n if (isSkeleton) {\n return (\n <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: t.labelGap }}>\n <div style={{ height: t.skeletonLabelH, background: grayNeutral.bgSkeleton, borderRadius: 6 }} />\n <div style={{ height: t.skeletonInputH, background: grayNeutral.bgSkeleton, border: `1px solid ${grayNeutral.bgSkeleton}`, borderRadius: 24 }} />\n </div>\n );\n }\n\n // ── Leading icon resolve ──────────────────────────────────────────────────\n // true → Circle (Figma default \"Icon/circle\"), component → custom, false → none\n const LeadingIconComponent: React.ElementType | null =\n leadingIcon === true\n ? Circle\n : leadingIcon\n ? (leadingIcon as React.ElementType)\n : null;\n\n // ── Trailing icons ────────────────────────────────────────────────────────\n const iconsToRender: InputFieldTrailingIcon[] =\n trailingIcons?.length ? trailingIcons : trailingIcon ? [trailingIcon] : [];\n\n // ── Text below input ──────────────────────────────────────────────────────\n const showText = isInvalid ? errorText : helperText;\n\n // ── Shared font style ─────────────────────────────────────────────────────\n const baseFont: React.CSSProperties = { fontFamily: font, fontWeight: 500 };\n\n return (\n /*\n * Outer wrapper — two-level gap structure matching Figma:\n * Level 1 (helperGap): separates [label + input block] from [helper text]\n * Level 2 (labelGap): separates [label row] from [input box]\n */\n <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: t.helperGap }}>\n\n {/* ── Level 1: label + input block ────────────────────────────────── */}\n <div style={{ display: 'flex', flexDirection: 'column', gap: t.labelGap, width: '100%' }}>\n\n {/* Label row */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, width: '100%' }}>\n {/* Left: label text + info icon */}\n <div style={{ display: 'flex', flex: '1 0 0', alignItems: 'center', gap: t.labelIconSize === 12 ? 4 : 6, minWidth: 0 }}>\n <span\n style={{\n ...baseFont,\n fontSize: t.labelFontSize,\n lineHeight: `${t.labelLineHeight}px`,\n color: labelColor,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {label}\n </span>\n {/* Info icon — fg/mid-on-white (same shade as label text) */}\n <Info\n size={t.labelIconSize}\n color={labelIconColor}\n strokeWidth={1.8}\n style={{ flexShrink: 0 }}\n />\n </div>\n\n {/* Right: remark or required marker */}\n {labelRemark && (\n <span\n style={{\n ...baseFont,\n fontSize: t.labelFontSize,\n lineHeight: `${t.labelLineHeight}px`,\n color: labelColor,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n }}\n >\n {labelRemark}\n </span>\n )}\n {required && (\n <span style={{ color: status.error, fontWeight: 800, flexShrink: 0 }}>*</span>\n )}\n </div>\n\n {/* Input box */}\n <div\n style={{\n background,\n border: `1px solid ${borderColor}`,\n height: t.inputHeight,\n width: '100%',\n borderRadius: 24,\n display: 'flex',\n alignItems: leadingDropdownText ? 'stretch' : 'center',\n ...(leadingDropdownText ? {} : { gap: 8, padding: `0 ${t.paddingX}px` }),\n overflow: 'hidden',\n boxShadow: isActive || isKeyboardFocus ? focusRingStyle : 'none',\n opacity: isDisabled ? 0.7 : 1,\n boxSizing: 'border-box',\n }}\n >\n {/* Leading: dropdown prefix OR icon */}\n {leadingDropdownText ? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n background: grayNeutral.bgWhite,\n padding: `${t.leadingPy}px ${t.leadingPr}px ${t.leadingPy}px ${t.leadingPl}px`,\n flexShrink: 0,\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: grayNeutral.fgHigh,\n whiteSpace: 'nowrap',\n }}\n >\n {leadingDropdownText}\n </span>\n <svg width={t.chevronSize} height={t.chevronSize} viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6L8 10L12 6\" stroke={grayNeutral.fgHigh} strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </div>\n ) : LeadingIconComponent ? (\n /* Leading icon in input → fg/high (#1B1D22) per Figma */\n <LeadingIconComponent\n size={t.iconSize}\n color={inputIconColor}\n strokeWidth={1.6}\n style={{ flexShrink: 0 }}\n />\n ) : null}\n\n {/* Text + accessories area */}\n <div\n style={{\n flex: '1 0 0',\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n height: '100%',\n minWidth: 0,\n ...(leadingDropdownText\n ? { borderLeft: `1px solid ${grayNeutral.borderLight}`, padding: `0 12px` }\n : {}),\n }}\n >\n {/* Input */}\n <input\n type=\"text\"\n value={value ?? ''}\n onChange={e => _onChange?.(e.target.value)}\n placeholder={placeholder}\n disabled={isDisabled}\n style={{\n ...baseFont,\n flex: '1 0 0',\n border: 'none',\n outline: 'none',\n background: 'transparent',\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: valueColor,\n width: '100%',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n cursor: isDisabled ? 'not-allowed' : 'text',\n }}\n />\n\n {/* Counter pill */}\n {counter && (\n <div\n style={{\n background: grayNeutral.bgLightgray,\n display: 'flex',\n gap: 2,\n alignItems: 'center',\n justifyContent: 'center',\n padding: t.counterPadding,\n borderRadius: t.counterRadius,\n flexShrink: 0,\n opacity: isDisabled ? 0.7 : 1,\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.counterFontSize,\n lineHeight: `${t.counterLineHeight}px`,\n color: grayNeutral.fgHigh,\n }}\n >\n {counter.value}\n </span>\n <span\n style={{\n ...baseFont,\n fontSize: t.counterFontSize,\n lineHeight: `${t.counterLineHeight}px`,\n color: grayNeutral.fgMid,\n }}\n >\n / {counter.max}\n </span>\n </div>\n )}\n\n {/* Unit text */}\n {unit && (\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: grayNeutral.fgHigh,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n maxWidth: 64,\n overflow: 'hidden',\n }}\n >\n {unit}\n </span>\n )}\n\n {/* Trailing icons */}\n {iconsToRender.length > 0 && (\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, flexShrink: 0 }}>\n {iconsToRender.map((ic, idx) => {\n const TrailingIcon = TRAILING_ICON_MAP[ic];\n return (\n <React.Fragment key={`${ic}-${idx}`}>\n {trailingIconSeparator && idx > 0 && (\n <div\n style={{\n width: 1,\n height: t.iconSize,\n background: grayNeutral.gray300,\n flexShrink: 0,\n alignSelf: 'center',\n }}\n />\n )}\n {/* Trailing icon → fg/high (#1B1D22) per Figma */}\n <TrailingIcon\n size={t.iconSize}\n color={inputIconColor}\n strokeWidth={1.6}\n style={{ flexShrink: 0 }}\n />\n </React.Fragment>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* ── Level 1: helper / error text ────────────────────────────────── */}\n {/*\n * No extra margin here — the outer helperGap (4px sm / 4px md / 6px lg)\n * from the flex container already provides the correct spacing from Figma.\n */}\n {showText && (\n <p\n style={{\n ...baseFont,\n margin: 0,\n fontSize: t.helperFontSize,\n lineHeight: `${t.helperLineHeight}px`,\n color: helperColor,\n width: '100%',\n }}\n >\n {showText}\n </p>\n )}\n </div>\n );\n};\n","// ─── Senestia Design System — Public API ─────────────────────────────────────\n//\n// import { Badge, InputField, tokens } from '@senestia/ui'\n//\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ── Components ────────────────────────────────────────────────────────────────\nexport { Badge } from './stories/Badge';\nexport { InputField } from './stories/InputField';\n\n// ── Component types ───────────────────────────────────────────────────────────\nexport type { BadgeProps, BadgeColor, BadgeSize, BadgeType } from './stories/Badge';\nexport type {\n InputFieldProps,\n InputFieldState,\n InputFieldSize,\n InputFieldTrailingIcon,\n InputFieldCounter,\n} from './stories/InputField';\n\n// ── Design Tokens ─────────────────────────────────────────────────────────────\nexport {\n // Colors\n grayNeutral,\n status,\n ciPrimary,\n oePrimary,\n interactive,\n // Spacing\n padding,\n radius,\n // Typography\n font,\n} from './stories/tokens';\n\n// ── Tokens namespace (for tree-shaking friendly usage) ────────────────────────\nimport * as _tokens from './stories/tokens';\nexport const tokens = _tokens;\n"],"mappings":"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"}
|
package/dist/senestia-ui.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`lucide-react`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`lucide-react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.SenestiaUI={},e.React,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var i=Object.create,a=Object.defineProperty,o=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,c=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty,u=(e,t)=>{let n={};for(var r in e)a(n,r,{get:e[r],enumerable:!0});return t||a(n,Symbol.toStringTag,{value:`Module`}),n},d=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=s(t),c=0,u=i.length,d;c<u;c++)d=i[c],!l.call(e,d)&&d!==n&&a(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=o(t,d))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:i(c(e)),d(t||!e||!e.__esModule?a(n,`default`,{value:e,enumerable:!0}):n,e)))(t);var f=`Sarabun, sans-serif`,p={Gray:{bg:`#f9fafb`,border:`#eaecf0`,text:`#06080b`,dot:`#667085`},Primary:{bg:`#f4f6f9`,border:`#e6ebf2`,text:`#1e2b3b`,dot:`#6c8fbe`},Error:{bg:`#fef0ef`,border:`#fbd2d0`,text:`#cc1a11`,dot:`#f04438`},Warning:{bg:`#fff9ee`,border:`#ffedcc`,text:`#db8f02`,dot:`#f79009`},Success:{bg:`#f0fdfa`,border:`#d2f9f1`,text:`#15a686`,dot:`#12b76a`},"Blue light":{bg:`#f0f9ff`,border:`#b9e6fe`,text:`#026aa2`,dot:`#0ba5ec`},Blue:{bg:`#eff8ff`,border:`#b2ddff`,text:`#175cd3`,dot:`#2e90fa`},Indigo:{bg:`#eef4ff`,border:`#c7d7fe`,text:`#3538cd`,dot:`#6172f3`},Purple:{bg:`#f4f3ff`,border:`#d9d6fe`,text:`#5925dc`,dot:`#7a5af8`},Pink:{bg:`#fef6fb`,border:`#fce7f6`,text:`#c11574`,dot:`#ee46bc`},Orange:{bg:`#fef6ee`,border:`#ffd6ae`,text:`#b93815`,dot:`#ef6820`},"Gray blue":{bg:`#f8f9fc`,border:`#d5d9eb`,text:`#363f72`,dot:`#717bbc`}},m={sm:{paddingX:8,paddingY:2,paddingXClose:{left:8,right:4},paddingXDot:{left:6,right:8},paddingPill:5,fontSize:12,lineHeight:18,dotSize:6,iconSize:12,closeSize:12},md:{paddingX:8,paddingY:2,paddingXClose:{left:8,right:4},paddingXDot:{left:6,right:8},paddingPill:6,fontSize:14,lineHeight:20,dotSize:6,iconSize:14,closeSize:14},lg:{paddingX:12,paddingY:4,paddingXClose:{left:12,right:6},paddingXDot:{left:8,right:12},paddingPill:8,fontSize:14,lineHeight:20,dotSize:8,iconSize:16,closeSize:16}},h=({label:e=`Label`,color:t=`Gray`,size:i=`sm`,type:a=`Idle`,icon:o,onClose:s})=>{let c=p[t],l=m[i],u={display:`inline-flex`,alignItems:`center`,backgroundColor:c.bg,border:`1px solid ${c.border}`,borderRadius:16,boxSizing:`border-box`,width:`fit-content`,fontFamily:f},d={fontSize:l.fontSize,lineHeight:`${l.lineHeight}px`,fontWeight:500,color:c.text,whiteSpace:`nowrap`,fontFamily:f,margin:0};if(a===`Idle`)return(0,r.jsx)(`span`,{style:{...u,padding:`${l.paddingY}px ${l.paddingX}px`},children:(0,r.jsx)(`span`,{style:d,children:e})});if(a===`Status Dot`)return(0,r.jsxs)(`span`,{style:{...u,gap:4,paddingTop:l.paddingY,paddingBottom:l.paddingY,paddingLeft:l.paddingXDot.left,paddingRight:l.paddingXDot.right},children:[(0,r.jsx)(`span`,{style:{display:`inline-block`,width:l.dotSize,height:l.dotSize,borderRadius:`50%`,backgroundColor:c.dot,flexShrink:0}}),(0,r.jsx)(`span`,{style:d,children:e})]});if(a===`Closable`)return(0,r.jsxs)(`span`,{style:{...u,gap:2,paddingTop:l.paddingY,paddingBottom:l.paddingY,paddingLeft:l.paddingXClose.left,paddingRight:l.paddingXClose.right},children:[(0,r.jsx)(`span`,{style:d,children:e}),(0,r.jsx)(`button`,{onClick:s,style:{display:`inline-flex`,alignItems:`center`,justifyContent:`center`,background:`none`,border:`none`,padding:2,borderRadius:3,cursor:`pointer`,color:c.text,flexShrink:0,lineHeight:1},"aria-label":`Remove`,children:(0,r.jsx)(n.X,{size:l.closeSize,strokeWidth:2.5})})]});if(a===`Pill color`){let e=o;return(0,r.jsx)(`span`,{style:{...u,padding:l.paddingPill},children:e?(0,r.jsx)(e,{size:l.iconSize,color:c.dot,strokeWidth:2}):(0,r.jsx)(`span`,{style:{display:`inline-block`,width:l.iconSize,height:l.iconSize,borderRadius:`50%`,backgroundColor:c.dot}})})}return null},g=u({ciPrimary:()=>y,font:()=>w,grayNeutral:()=>_,interactive:()=>x,oePrimary:()=>b,padding:()=>S,radius:()=>C,status:()=>v}),_={fgHigh:`#1B1D22`,fgMid:`#6A6E83`,fgLow:`#9A9DAD`,bgWhite:`#FFFFFF`,bgLightgray:`#F8F8F9`,bgDisabled:`#F3F4F6`,borderMidgray:`#CFD1D9`,borderLight:`#EBECEF`,borderDisabled:`#E5EAF1`,gray300:`#D0D5DD`,bgSkeleton:`#EEF0F3`,bgDisabledStrong:`#EBECEF`},v={error:`#DB1439`,warning:`#DB8F02`,success:`#15A686`},y={fgLow:`#C4B3F6`,fgHigh:`#802CEB`,bgLow:`#D4C9F6`,bgMid:`#802CEB`,bgHigh:`#5A1DA9`,borderMid:`#996CF3`,borderHigh:`#802CEB`},b={fgLow:`#5273A1`,fgHigh:`#3A5274`,bgLowest:`#EFF2F6`,bgLow:`#6E90BF`,bgMid:`#5273A1`,bgHigh:`#3A5274`,borderLowest:`#C6D2E3`,borderLow:`#9CB3D2`,borderMid:`#5273A1`,p300:`#809BBF`,linkBlue:`#3C5BD5`},x={activeBorder:b.fgLow,hoverBorder:`#3B82F6`,focusRing:`#D7DFEA`,invalidBorder:v.error},S={"PD-0":0,"PD-1":1,"PD-2":2,"PD-3":4,"PD-4":6,"PD-5":8,"PD-6":12,"PD-7":16,"PD-8":24,"PD-9":32,"PD-10":40,"PD-11":48,"PD-12":56,"PD-13":64,"PD-14":72,"PD-15":80},C={"CR-0":0,"CR-1":2,"CR-2":4,"CR-3":8,"CR-4":12,"CR-5":16,"CR-6":20,"CR-7":24,"CR-8":32,"CR-9":48,"CR-10":100},w=`Sarabun, sans-serif`,T={sm:{inputHeight:32,labelFontSize:12,labelLineHeight:18,inputFontSize:14,inputLineHeight:20,helperFontSize:12,helperLineHeight:18,paddingX:12,iconSize:16,labelIconSize:12,labelGap:4,helperGap:4,leadingPl:8,leadingPr:4,leadingPy:6,chevronSize:14,counterPadding:`1px 4px`,counterRadius:4,counterFontSize:12,counterLineHeight:18,skeletonLabelH:18,skeletonInputH:32},md:{inputHeight:40,labelFontSize:14,labelLineHeight:20,inputFontSize:16,inputLineHeight:24,helperFontSize:14,helperLineHeight:20,paddingX:16,iconSize:20,labelIconSize:14,labelGap:6,helperGap:4,leadingPl:12,leadingPr:8,leadingPy:8,chevronSize:16,counterPadding:`2px 8px`,counterRadius:8,counterFontSize:14,counterLineHeight:20,skeletonLabelH:20,skeletonInputH:40},lg:{inputHeight:48,labelFontSize:16,labelLineHeight:24,inputFontSize:16,inputLineHeight:24,helperFontSize:14,helperLineHeight:20,paddingX:16,iconSize:20,labelIconSize:16,labelGap:8,helperGap:6,leadingPl:16,leadingPr:8,leadingPy:12,chevronSize:16,counterPadding:`2px 8px`,counterRadius:8,counterFontSize:14,counterLineHeight:20,skeletonLabelH:24,skeletonInputH:48}},E=`0 0 0 2px ${x.focusRing}`,D=e=>{let t=e??`Idle`;return{s:t,isInvalid:t.includes(`invalid`),isHover:t.includes(`hover`),isActive:t===`Active`||t===`Keyboard focus`||t.endsWith(`active`),isDisabled:t===`Disable`,isSkeleton:t===`Skeleton`,isFilled:t.includes(`Filled`),isKeyboardFocus:t===`Keyboard focus`}},O={clear:n.XCircle,search:n.Search,password:n.Eye},k=({label:e,required:i=!1,labelRemark:a,placeholder:o=`Placeholder`,value:s,onChange:c,helperText:l,errorText:u,state:d=`Idle`,size:f=`md`,leadingDropdownText:p,leadingIcon:m,counter:h,unit:g,trailingIcon:y,trailingIcons:b,trailingIconSeparator:S=!1})=>{let{isInvalid:C,isHover:k,isActive:A,isDisabled:j,isSkeleton:M,isKeyboardFocus:N}=D(d),P=T[f],F=C?x.invalidBorder:A||N?x.activeBorder:k?x.hoverBorder:_.borderMidgray,I=j?_.bgDisabled:k?_.bgLightgray:_.bgWhite,L=j?_.fgLow:_.fgMid,R=_.fgLow,z=j?_.fgLow:_.fgHigh,B=j?_.fgLow:_.fgHigh,V=j?_.fgLow:_.fgMid,H=C?v.error:_.fgMid;if(M)return(0,r.jsxs)(`div`,{style:{width:320,display:`flex`,flexDirection:`column`,gap:P.labelGap},children:[(0,r.jsx)(`div`,{style:{height:P.skeletonLabelH,background:_.bgSkeleton,borderRadius:6}}),(0,r.jsx)(`div`,{style:{height:P.skeletonInputH,background:_.bgSkeleton,border:`1px solid ${_.bgSkeleton}`,borderRadius:24}})]});let U=m===!0?n.Circle:m||null,W=b?.length?b:y?[y]:[],G=C?u:l,K={fontFamily:w,fontWeight:500};return(0,r.jsxs)(`div`,{style:{width:320,display:`flex`,flexDirection:`column`,gap:P.helperGap},children:[(0,r.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,gap:P.labelGap,width:`100%`},children:[(0,r.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:4,width:`100%`},children:[(0,r.jsxs)(`div`,{style:{display:`flex`,flex:`1 0 0`,alignItems:`center`,gap:P.labelIconSize===12?4:6,minWidth:0},children:[(0,r.jsx)(`span`,{style:{...K,fontSize:P.labelFontSize,lineHeight:`${P.labelLineHeight}px`,color:L,whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`},children:e}),(0,r.jsx)(n.Info,{size:P.labelIconSize,color:V,strokeWidth:1.8,style:{flexShrink:0}})]}),a&&(0,r.jsx)(`span`,{style:{...K,fontSize:P.labelFontSize,lineHeight:`${P.labelLineHeight}px`,color:L,whiteSpace:`nowrap`,flexShrink:0},children:a}),i&&(0,r.jsx)(`span`,{style:{color:v.error,fontWeight:800,flexShrink:0},children:`*`})]}),(0,r.jsxs)(`div`,{style:{background:I,border:`1px solid ${F}`,height:P.inputHeight,width:`100%`,borderRadius:24,display:`flex`,alignItems:p?`stretch`:`center`,...p?{}:{gap:8,padding:`0 ${P.paddingX}px`},overflow:`hidden`,boxShadow:A||N?E:`none`,opacity:j?.7:1,boxSizing:`border-box`},children:[p?(0,r.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:4,background:_.bgWhite,padding:`${P.leadingPy}px ${P.leadingPr}px ${P.leadingPy}px ${P.leadingPl}px`,flexShrink:0},children:[(0,r.jsx)(`span`,{style:{...K,fontSize:P.inputFontSize,lineHeight:`${P.inputLineHeight}px`,color:_.fgHigh,whiteSpace:`nowrap`},children:p}),(0,r.jsx)(`svg`,{width:P.chevronSize,height:P.chevronSize,viewBox:`0 0 16 16`,fill:`none`,children:(0,r.jsx)(`path`,{d:`M4 6L8 10L12 6`,stroke:_.fgHigh,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`})})]}):U?(0,r.jsx)(U,{size:P.iconSize,color:B,strokeWidth:1.6,style:{flexShrink:0}}):null,(0,r.jsxs)(`div`,{style:{flex:`1 0 0`,display:`flex`,alignItems:`center`,gap:8,height:`100%`,minWidth:0,...p?{borderLeft:`1px solid ${_.borderLight}`,padding:`0 12px`}:{}},children:[(0,r.jsx)(`div`,{style:{flex:`1 0 0`,overflow:`hidden`,display:`flex`,alignItems:`center`},children:(0,r.jsx)(`span`,{style:{...K,fontSize:P.inputFontSize,lineHeight:`${P.inputLineHeight}px`,color:s?z:R,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`,display:`block`,width:`100%`},children:s||o})}),h&&(0,r.jsxs)(`div`,{style:{background:_.bgLightgray,display:`flex`,gap:2,alignItems:`center`,justifyContent:`center`,padding:P.counterPadding,borderRadius:P.counterRadius,flexShrink:0,opacity:j?.7:1},children:[(0,r.jsx)(`span`,{style:{...K,fontSize:P.counterFontSize,lineHeight:`${P.counterLineHeight}px`,color:_.fgHigh},children:h.value}),(0,r.jsxs)(`span`,{style:{...K,fontSize:P.counterFontSize,lineHeight:`${P.counterLineHeight}px`,color:_.fgMid},children:[`/ `,h.max]})]}),g&&(0,r.jsx)(`span`,{style:{...K,fontSize:P.inputFontSize,lineHeight:`${P.inputLineHeight}px`,color:_.fgHigh,whiteSpace:`nowrap`,flexShrink:0,maxWidth:64,overflow:`hidden`},children:g}),W.length>0&&(0,r.jsx)(`div`,{style:{display:`flex`,alignItems:`center`,gap:4,flexShrink:0},children:W.map((e,n)=>{let i=O[e];return(0,r.jsxs)(t.default.Fragment,{children:[S&&n>0&&(0,r.jsx)(`div`,{style:{width:1,height:P.iconSize,background:_.gray300,flexShrink:0,alignSelf:`center`}}),(0,r.jsx)(i,{size:P.iconSize,color:B,strokeWidth:1.6,style:{flexShrink:0}})]},`${e}-${n}`)})})]})]})]}),G&&(0,r.jsx)(`p`,{style:{...K,margin:0,fontSize:P.helperFontSize,lineHeight:`${P.helperLineHeight}px`,color:H,width:`100%`},children:G})]})},A=g;e.Badge=h,e.InputField=k,e.ciPrimary=y,e.font=w,e.grayNeutral=_,e.interactive=x,e.oePrimary=b,e.padding=S,e.radius=C,e.status=v,e.tokens=A});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`lucide-react`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`lucide-react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.SenestiaUI={},e.React,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var i=Object.create,a=Object.defineProperty,o=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,c=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty,u=(e,t)=>{let n={};for(var r in e)a(n,r,{get:e[r],enumerable:!0});return t||a(n,Symbol.toStringTag,{value:`Module`}),n},d=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=s(t),c=0,u=i.length,d;c<u;c++)d=i[c],!l.call(e,d)&&d!==n&&a(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=o(t,d))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:i(c(e)),d(t||!e||!e.__esModule?a(n,`default`,{value:e,enumerable:!0}):n,e)))(t);var f=`Sarabun, sans-serif`,p={Gray:{bg:`#f9fafb`,border:`#eaecf0`,text:`#06080b`,dot:`#667085`},Primary:{bg:`#f4f6f9`,border:`#e6ebf2`,text:`#1e2b3b`,dot:`#6c8fbe`},Error:{bg:`#fef0ef`,border:`#fbd2d0`,text:`#cc1a11`,dot:`#f04438`},Warning:{bg:`#fff9ee`,border:`#ffedcc`,text:`#db8f02`,dot:`#f79009`},Success:{bg:`#f0fdfa`,border:`#d2f9f1`,text:`#15a686`,dot:`#12b76a`},"Blue light":{bg:`#f0f9ff`,border:`#b9e6fe`,text:`#026aa2`,dot:`#0ba5ec`},Blue:{bg:`#eff8ff`,border:`#b2ddff`,text:`#175cd3`,dot:`#2e90fa`},Indigo:{bg:`#eef4ff`,border:`#c7d7fe`,text:`#3538cd`,dot:`#6172f3`},Purple:{bg:`#f4f3ff`,border:`#d9d6fe`,text:`#5925dc`,dot:`#7a5af8`},Pink:{bg:`#fef6fb`,border:`#fce7f6`,text:`#c11574`,dot:`#ee46bc`},Orange:{bg:`#fef6ee`,border:`#ffd6ae`,text:`#b93815`,dot:`#ef6820`},"Gray blue":{bg:`#f8f9fc`,border:`#d5d9eb`,text:`#363f72`,dot:`#717bbc`}},m={sm:{paddingX:8,paddingY:2,paddingXClose:{left:8,right:4},paddingXDot:{left:6,right:8},paddingPill:5,fontSize:12,lineHeight:18,dotSize:6,iconSize:12,closeSize:12},md:{paddingX:8,paddingY:2,paddingXClose:{left:8,right:4},paddingXDot:{left:6,right:8},paddingPill:6,fontSize:14,lineHeight:20,dotSize:6,iconSize:14,closeSize:14},lg:{paddingX:12,paddingY:4,paddingXClose:{left:12,right:6},paddingXDot:{left:8,right:12},paddingPill:8,fontSize:14,lineHeight:20,dotSize:8,iconSize:16,closeSize:16}},h=({label:e=`Label`,color:t=`Gray`,size:i=`sm`,type:a=`Idle`,icon:o,onClose:s})=>{let c=p[t],l=m[i],u={display:`inline-flex`,alignItems:`center`,backgroundColor:c.bg,border:`1px solid ${c.border}`,borderRadius:16,boxSizing:`border-box`,width:`fit-content`,fontFamily:f},d={fontSize:l.fontSize,lineHeight:`${l.lineHeight}px`,fontWeight:500,color:c.text,whiteSpace:`nowrap`,fontFamily:f,margin:0};if(a===`Idle`)return(0,r.jsx)(`span`,{style:{...u,padding:`${l.paddingY}px ${l.paddingX}px`},children:(0,r.jsx)(`span`,{style:d,children:e})});if(a===`Status Dot`)return(0,r.jsxs)(`span`,{style:{...u,gap:4,paddingTop:l.paddingY,paddingBottom:l.paddingY,paddingLeft:l.paddingXDot.left,paddingRight:l.paddingXDot.right},children:[(0,r.jsx)(`span`,{style:{display:`inline-block`,width:l.dotSize,height:l.dotSize,borderRadius:`50%`,backgroundColor:c.dot,flexShrink:0}}),(0,r.jsx)(`span`,{style:d,children:e})]});if(a===`Closable`)return(0,r.jsxs)(`span`,{style:{...u,gap:2,paddingTop:l.paddingY,paddingBottom:l.paddingY,paddingLeft:l.paddingXClose.left,paddingRight:l.paddingXClose.right},children:[(0,r.jsx)(`span`,{style:d,children:e}),(0,r.jsx)(`button`,{onClick:s,style:{display:`inline-flex`,alignItems:`center`,justifyContent:`center`,background:`none`,border:`none`,padding:2,borderRadius:3,cursor:`pointer`,color:c.text,flexShrink:0,lineHeight:1},"aria-label":`Remove`,children:(0,r.jsx)(n.X,{size:l.closeSize,strokeWidth:2.5})})]});if(a===`Pill color`){let e=o;return(0,r.jsx)(`span`,{style:{...u,padding:l.paddingPill},children:e?(0,r.jsx)(e,{size:l.iconSize,color:c.dot,strokeWidth:2}):(0,r.jsx)(`span`,{style:{display:`inline-block`,width:l.iconSize,height:l.iconSize,borderRadius:`50%`,backgroundColor:c.dot}})})}return null},g=u({ciPrimary:()=>y,font:()=>w,grayNeutral:()=>_,interactive:()=>x,oePrimary:()=>b,padding:()=>S,radius:()=>C,status:()=>v}),_={fgHigh:`#1B1D22`,fgMid:`#6A6E83`,fgLow:`#9A9DAD`,bgWhite:`#FFFFFF`,bgLightgray:`#F8F8F9`,bgDisabled:`#F3F4F6`,borderMidgray:`#CFD1D9`,borderLight:`#EBECEF`,borderDisabled:`#E5EAF1`,gray300:`#D0D5DD`,bgSkeleton:`#EEF0F3`,bgDisabledStrong:`#EBECEF`},v={error:`#DB1439`,warning:`#DB8F02`,success:`#15A686`},y={fgLow:`#C4B3F6`,fgHigh:`#802CEB`,bgLow:`#D4C9F6`,bgMid:`#802CEB`,bgHigh:`#5A1DA9`,borderMid:`#996CF3`,borderHigh:`#802CEB`},b={fgLow:`#5273A1`,fgHigh:`#3A5274`,bgLowest:`#EFF2F6`,bgLow:`#6E90BF`,bgMid:`#5273A1`,bgHigh:`#3A5274`,borderLowest:`#C6D2E3`,borderLow:`#9CB3D2`,borderMid:`#5273A1`,p300:`#809BBF`,linkBlue:`#3C5BD5`},x={activeBorder:b.fgLow,hoverBorder:`#3B82F6`,focusRing:`#D7DFEA`,invalidBorder:v.error},S={"PD-0":0,"PD-1":1,"PD-2":2,"PD-3":4,"PD-4":6,"PD-5":8,"PD-6":12,"PD-7":16,"PD-8":24,"PD-9":32,"PD-10":40,"PD-11":48,"PD-12":56,"PD-13":64,"PD-14":72,"PD-15":80},C={"CR-0":0,"CR-1":2,"CR-2":4,"CR-3":8,"CR-4":12,"CR-5":16,"CR-6":20,"CR-7":24,"CR-8":32,"CR-9":48,"CR-10":100},w=`Sarabun, sans-serif`,T={sm:{inputHeight:32,labelFontSize:12,labelLineHeight:18,inputFontSize:14,inputLineHeight:20,helperFontSize:12,helperLineHeight:18,paddingX:12,iconSize:16,labelIconSize:12,labelGap:4,helperGap:4,leadingPl:8,leadingPr:4,leadingPy:6,chevronSize:14,counterPadding:`1px 4px`,counterRadius:4,counterFontSize:12,counterLineHeight:18,skeletonLabelH:18,skeletonInputH:32},md:{inputHeight:40,labelFontSize:14,labelLineHeight:20,inputFontSize:16,inputLineHeight:24,helperFontSize:14,helperLineHeight:20,paddingX:16,iconSize:20,labelIconSize:14,labelGap:6,helperGap:4,leadingPl:12,leadingPr:8,leadingPy:8,chevronSize:16,counterPadding:`2px 8px`,counterRadius:8,counterFontSize:14,counterLineHeight:20,skeletonLabelH:20,skeletonInputH:40},lg:{inputHeight:48,labelFontSize:16,labelLineHeight:24,inputFontSize:16,inputLineHeight:24,helperFontSize:14,helperLineHeight:20,paddingX:16,iconSize:20,labelIconSize:16,labelGap:8,helperGap:6,leadingPl:16,leadingPr:8,leadingPy:12,chevronSize:16,counterPadding:`2px 8px`,counterRadius:8,counterFontSize:14,counterLineHeight:20,skeletonLabelH:24,skeletonInputH:48}},E=`0 0 0 2px ${x.focusRing}`,D=e=>{let t=e??`Idle`;return{s:t,isInvalid:t.includes(`invalid`),isHover:t.includes(`hover`),isActive:t===`Active`||t===`Keyboard focus`||t.endsWith(`active`),isDisabled:t===`Disable`,isSkeleton:t===`Skeleton`,isFilled:t.includes(`Filled`),isKeyboardFocus:t===`Keyboard focus`}},O={clear:n.XCircle,search:n.Search,password:n.Eye},k=({label:e,required:i=!1,labelRemark:a,placeholder:o=`Placeholder`,value:s,onChange:c,helperText:l,errorText:u,state:d=`Idle`,size:f=`md`,leadingDropdownText:p,leadingIcon:m,counter:h,unit:g,trailingIcon:y,trailingIcons:b,trailingIconSeparator:S=!1})=>{let{isInvalid:C,isHover:k,isActive:A,isDisabled:j,isSkeleton:M,isKeyboardFocus:N}=D(d),P=T[f],F=C?x.invalidBorder:A||N?x.activeBorder:k?x.hoverBorder:_.borderMidgray,I=j?_.bgDisabled:k?_.bgLightgray:_.bgWhite,L=j?_.fgLow:_.fgMid,R=j?_.fgLow:_.fgHigh,z=j?_.fgLow:_.fgHigh,B=j?_.fgLow:_.fgMid,V=C?v.error:_.fgMid;if(M)return(0,r.jsxs)(`div`,{style:{width:320,display:`flex`,flexDirection:`column`,gap:P.labelGap},children:[(0,r.jsx)(`div`,{style:{height:P.skeletonLabelH,background:_.bgSkeleton,borderRadius:6}}),(0,r.jsx)(`div`,{style:{height:P.skeletonInputH,background:_.bgSkeleton,border:`1px solid ${_.bgSkeleton}`,borderRadius:24}})]});let H=m===!0?n.Circle:m||null,U=b?.length?b:y?[y]:[],W=C?u:l,G={fontFamily:w,fontWeight:500};return(0,r.jsxs)(`div`,{style:{width:320,display:`flex`,flexDirection:`column`,gap:P.helperGap},children:[(0,r.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,gap:P.labelGap,width:`100%`},children:[(0,r.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:4,width:`100%`},children:[(0,r.jsxs)(`div`,{style:{display:`flex`,flex:`1 0 0`,alignItems:`center`,gap:P.labelIconSize===12?4:6,minWidth:0},children:[(0,r.jsx)(`span`,{style:{...G,fontSize:P.labelFontSize,lineHeight:`${P.labelLineHeight}px`,color:L,whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`},children:e}),(0,r.jsx)(n.Info,{size:P.labelIconSize,color:B,strokeWidth:1.8,style:{flexShrink:0}})]}),a&&(0,r.jsx)(`span`,{style:{...G,fontSize:P.labelFontSize,lineHeight:`${P.labelLineHeight}px`,color:L,whiteSpace:`nowrap`,flexShrink:0},children:a}),i&&(0,r.jsx)(`span`,{style:{color:v.error,fontWeight:800,flexShrink:0},children:`*`})]}),(0,r.jsxs)(`div`,{style:{background:I,border:`1px solid ${F}`,height:P.inputHeight,width:`100%`,borderRadius:24,display:`flex`,alignItems:p?`stretch`:`center`,...p?{}:{gap:8,padding:`0 ${P.paddingX}px`},overflow:`hidden`,boxShadow:A||N?E:`none`,opacity:j?.7:1,boxSizing:`border-box`},children:[p?(0,r.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:4,background:_.bgWhite,padding:`${P.leadingPy}px ${P.leadingPr}px ${P.leadingPy}px ${P.leadingPl}px`,flexShrink:0},children:[(0,r.jsx)(`span`,{style:{...G,fontSize:P.inputFontSize,lineHeight:`${P.inputLineHeight}px`,color:_.fgHigh,whiteSpace:`nowrap`},children:p}),(0,r.jsx)(`svg`,{width:P.chevronSize,height:P.chevronSize,viewBox:`0 0 16 16`,fill:`none`,children:(0,r.jsx)(`path`,{d:`M4 6L8 10L12 6`,stroke:_.fgHigh,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`})})]}):H?(0,r.jsx)(H,{size:P.iconSize,color:z,strokeWidth:1.6,style:{flexShrink:0}}):null,(0,r.jsxs)(`div`,{style:{flex:`1 0 0`,display:`flex`,alignItems:`center`,gap:8,height:`100%`,minWidth:0,...p?{borderLeft:`1px solid ${_.borderLight}`,padding:`0 12px`}:{}},children:[(0,r.jsx)(`input`,{type:`text`,value:s??``,onChange:e=>c?.(e.target.value),placeholder:o,disabled:j,style:{...G,flex:`1 0 0`,border:`none`,outline:`none`,background:`transparent`,fontSize:P.inputFontSize,lineHeight:`${P.inputLineHeight}px`,color:R,width:`100%`,minWidth:0,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`,cursor:j?`not-allowed`:`text`}}),h&&(0,r.jsxs)(`div`,{style:{background:_.bgLightgray,display:`flex`,gap:2,alignItems:`center`,justifyContent:`center`,padding:P.counterPadding,borderRadius:P.counterRadius,flexShrink:0,opacity:j?.7:1},children:[(0,r.jsx)(`span`,{style:{...G,fontSize:P.counterFontSize,lineHeight:`${P.counterLineHeight}px`,color:_.fgHigh},children:h.value}),(0,r.jsxs)(`span`,{style:{...G,fontSize:P.counterFontSize,lineHeight:`${P.counterLineHeight}px`,color:_.fgMid},children:[`/ `,h.max]})]}),g&&(0,r.jsx)(`span`,{style:{...G,fontSize:P.inputFontSize,lineHeight:`${P.inputLineHeight}px`,color:_.fgHigh,whiteSpace:`nowrap`,flexShrink:0,maxWidth:64,overflow:`hidden`},children:g}),U.length>0&&(0,r.jsx)(`div`,{style:{display:`flex`,alignItems:`center`,gap:4,flexShrink:0},children:U.map((e,n)=>{let i=O[e];return(0,r.jsxs)(t.default.Fragment,{children:[S&&n>0&&(0,r.jsx)(`div`,{style:{width:1,height:P.iconSize,background:_.gray300,flexShrink:0,alignSelf:`center`}}),(0,r.jsx)(i,{size:P.iconSize,color:z,strokeWidth:1.6,style:{flexShrink:0}})]},`${e}-${n}`)})})]})]})]}),W&&(0,r.jsx)(`p`,{style:{...G,margin:0,fontSize:P.helperFontSize,lineHeight:`${P.helperLineHeight}px`,color:V,width:`100%`},children:W})]})},A=g;e.Badge=h,e.InputField=k,e.ciPrimary=y,e.font=w,e.grayNeutral=_,e.interactive=x,e.oePrimary=b,e.padding=S,e.radius=C,e.status=v,e.tokens=A});
|
|
2
2
|
//# sourceMappingURL=senestia-ui.umd.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"senestia-ui.umd.js","names":[],"sources":["../src/stories/Badge.tsx","../src/stories/tokens.ts","../src/stories/InputField.tsx","../src/index.ts"],"sourcesContent":["import React from 'react';\nimport { X } from 'lucide-react';\n\n// ─── Design System Font ──────────────────────────────────────────────────────\nconst font = 'Sarabun, sans-serif';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type BadgeColor =\n | 'Gray'\n | 'Primary'\n | 'Error'\n | 'Warning'\n | 'Success'\n | 'Blue light'\n | 'Blue'\n | 'Indigo'\n | 'Purple'\n | 'Pink'\n | 'Orange'\n | 'Gray blue';\n\nexport type BadgeSize = 'sm' | 'md' | 'lg';\n\nexport type BadgeType = 'Idle' | 'Status Dot' | 'Closable' | 'Pill color';\n\nexport interface BadgeProps {\n /** Badge label text */\n label?: string;\n /** Color variant */\n color?: BadgeColor;\n /** Size variant */\n size?: BadgeSize;\n /** Type / style variant */\n type?: BadgeType;\n /** Icon to render inside Pill color type (Lucide icon component) */\n icon?: React.ElementType;\n /** Called when close button is clicked (Closable type) */\n onClose?: () => void;\n}\n\n// ─── Color Tokens ────────────────────────────────────────────────────────────\n\nconst COLOR_TOKENS: Record<\n BadgeColor,\n { bg: string; border: string; text: string; dot: string }\n> = {\n Gray: { bg: '#f9fafb', border: '#eaecf0', text: '#06080b', dot: '#667085' },\n Primary: { bg: '#f4f6f9', border: '#e6ebf2', text: '#1e2b3b', dot: '#6c8fbe' },\n Error: { bg: '#fef0ef', border: '#fbd2d0', text: '#cc1a11', dot: '#f04438' },\n Warning: { bg: '#fff9ee', border: '#ffedcc', text: '#db8f02', dot: '#f79009' },\n Success: { bg: '#f0fdfa', border: '#d2f9f1', text: '#15a686', dot: '#12b76a' },\n 'Blue light': { bg: '#f0f9ff', border: '#b9e6fe', text: '#026aa2', dot: '#0ba5ec' },\n Blue: { bg: '#eff8ff', border: '#b2ddff', text: '#175cd3', dot: '#2e90fa' },\n Indigo: { bg: '#eef4ff', border: '#c7d7fe', text: '#3538cd', dot: '#6172f3' },\n Purple: { bg: '#f4f3ff', border: '#d9d6fe', text: '#5925dc', dot: '#7a5af8' },\n Pink: { bg: '#fef6fb', border: '#fce7f6', text: '#c11574', dot: '#ee46bc' },\n Orange: { bg: '#fef6ee', border: '#ffd6ae', text: '#b93815', dot: '#ef6820' },\n 'Gray blue':{ bg: '#f8f9fc', border: '#d5d9eb', text: '#363f72', dot: '#717bbc' },\n};\n\n// ─── Size Tokens ─────────────────────────────────────────────────────────────\n\nconst SIZE_TOKENS: Record<\n BadgeSize,\n {\n paddingX: number;\n paddingY: number;\n paddingXClose: { left: number; right: number };\n paddingXDot: { left: number; right: number };\n paddingPill: number;\n fontSize: number;\n lineHeight: number;\n dotSize: number;\n iconSize: number;\n closeSize: number;\n }\n> = {\n sm: {\n paddingX: 8, paddingY: 2,\n paddingXClose: { left: 8, right: 4 },\n paddingXDot: { left: 6, right: 8 },\n paddingPill: 5,\n fontSize: 12, lineHeight: 18,\n dotSize: 6, iconSize: 12, closeSize: 12,\n },\n md: {\n paddingX: 8, paddingY: 2,\n paddingXClose: { left: 8, right: 4 },\n paddingXDot: { left: 6, right: 8 },\n paddingPill: 6,\n fontSize: 14, lineHeight: 20,\n dotSize: 6, iconSize: 14, closeSize: 14,\n },\n lg: {\n paddingX: 12, paddingY: 4,\n paddingXClose: { left: 12, right: 6 },\n paddingXDot: { left: 8, right: 12 },\n paddingPill: 8,\n fontSize: 14, lineHeight: 20,\n dotSize: 8, iconSize: 16, closeSize: 16,\n },\n};\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport const Badge: React.FC<BadgeProps> = ({\n label = 'Label',\n color = 'Gray',\n size = 'sm',\n type = 'Idle',\n icon: IconComponent,\n onClose,\n}) => {\n const c = COLOR_TOKENS[color];\n const s = SIZE_TOKENS[size];\n\n // ── Shared wrapper style ──────────────────────────────────────────────────\n const baseWrapper: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n backgroundColor: c.bg,\n border: `1px solid ${c.border}`,\n borderRadius: 16,\n boxSizing: 'border-box',\n width: 'fit-content',\n fontFamily: font,\n };\n\n // ── Text style ────────────────────────────────────────────────────────────\n const textStyle: React.CSSProperties = {\n fontSize: s.fontSize,\n lineHeight: `${s.lineHeight}px`,\n fontWeight: 500,\n color: c.text,\n whiteSpace: 'nowrap',\n fontFamily: font,\n margin: 0,\n };\n\n // ── Idle ─────────────────────────────────────────────────────────────────\n if (type === 'Idle') {\n return (\n <span\n style={{\n ...baseWrapper,\n padding: `${s.paddingY}px ${s.paddingX}px`,\n }}\n >\n <span style={textStyle}>{label}</span>\n </span>\n );\n }\n\n // ── Status Dot ────────────────────────────────────────────────────────────\n if (type === 'Status Dot') {\n return (\n <span\n style={{\n ...baseWrapper,\n gap: 4,\n paddingTop: s.paddingY,\n paddingBottom: s.paddingY,\n paddingLeft: s.paddingXDot.left,\n paddingRight: s.paddingXDot.right,\n }}\n >\n {/* Dot */}\n <span\n style={{\n display: 'inline-block',\n width: s.dotSize,\n height: s.dotSize,\n borderRadius: '50%',\n backgroundColor: c.dot,\n flexShrink: 0,\n }}\n />\n <span style={textStyle}>{label}</span>\n </span>\n );\n }\n\n // ── Closable ──────────────────────────────────────────────────────────────\n if (type === 'Closable') {\n return (\n <span\n style={{\n ...baseWrapper,\n gap: 2,\n paddingTop: s.paddingY,\n paddingBottom: s.paddingY,\n paddingLeft: s.paddingXClose.left,\n paddingRight: s.paddingXClose.right,\n }}\n >\n <span style={textStyle}>{label}</span>\n <button\n onClick={onClose}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'none',\n border: 'none',\n padding: 2,\n borderRadius: 3,\n cursor: 'pointer',\n color: c.text,\n flexShrink: 0,\n lineHeight: 1,\n }}\n aria-label=\"Remove\"\n >\n <X size={s.closeSize} strokeWidth={2.5} />\n </button>\n </span>\n );\n }\n\n // ── Pill color (icon only) ────────────────────────────────────────────────\n if (type === 'Pill color') {\n const PillIcon = IconComponent;\n return (\n <span\n style={{\n ...baseWrapper,\n padding: s.paddingPill,\n }}\n >\n {PillIcon ? (\n <PillIcon size={s.iconSize} color={c.dot} strokeWidth={2} />\n ) : (\n // Default: colored circle dot\n <span\n style={{\n display: 'inline-block',\n width: s.iconSize,\n height: s.iconSize,\n borderRadius: '50%',\n backgroundColor: c.dot,\n }}\n />\n )}\n </span>\n );\n }\n\n return null;\n};\n","/**\n * Senestia Design System — Semantic Color Tokens\n *\n * ┌─────────────────────────────────────────────────────────────┐\n * │ Source: Figma DS-01 · Foundation → Semantic Color │\n * │ Use these tokens in components instead of raw hex values. │\n * └─────────────────────────────────────────────────────────────┘\n */\n\n// ─── Gray-Neutral ─────────────────────────────────────────────────────────────\n\nexport const grayNeutral = {\n /** Semantic/Gray-Neutral/fg/high — primary text, dark icons */\n fgHigh: '#1B1D22',\n /** Semantic/Gray-Neutral/fg/mid-on-white — label text, helper text, secondary icons */\n fgMid: '#6A6E83',\n /** Semantic/Gray-Neutral/fg/low-on-white — placeholder, disabled text */\n fgLow: '#9A9DAD',\n\n /** Semantic/Gray-Neutral/bg/white */\n bgWhite: '#FFFFFF',\n /** Semantic/Gray-Neutral/bg/lightgray — counter pill, subtle backgrounds */\n bgLightgray: '#F8F8F9',\n /** Semantic/Gray-Neutral/bg/disabled */\n bgDisabled: '#F3F4F6',\n\n /** Semantic/Gray-Neutral/border/midgray — default input border */\n borderMidgray: '#CFD1D9',\n /** Semantic/Gray-Neutral/border/light — dividers, card borders */\n borderLight: '#EBECEF',\n /** Disabled border (checkbox, input) */\n borderDisabled: '#E5EAF1',\n\n /** Gray/300 — icon separators */\n gray300: '#D0D5DD',\n /** Skeleton loading shimmer */\n bgSkeleton: '#EEF0F3',\n /** Strong disabled background (checkbox) */\n bgDisabledStrong: '#EBECEF',\n} as const;\n\n// ─── Status ───────────────────────────────────────────────────────────────────\n\nexport const status = {\n /** Error / invalid state */\n error: '#DB1439',\n /** Warning */\n warning: '#DB8F02',\n /** Success */\n success: '#15A686',\n} as const;\n\n// ─── CI Primary (Senestia brand purple) ───────────────────────────────────────\n\nexport const ciPrimary = {\n fgLow: '#C4B3F6',\n fgHigh: '#802CEB',\n bgLow: '#D4C9F6',\n bgMid: '#802CEB',\n bgHigh: '#5A1DA9',\n borderMid: '#996CF3',\n borderHigh: '#802CEB',\n} as const;\n\n// ─── OE Theme (OE brand blue) ─────────────────────────────────────────────────\n\nexport const oePrimary = {\n fgLow: '#5273A1',\n fgHigh: '#3A5274',\n bgLowest: '#EFF2F6', // selected item background in pickers\n bgLow: '#6E90BF',\n bgMid: '#5273A1',\n bgHigh: '#3A5274',\n borderLowest:'#C6D2E3', // focused item border\n borderLow: '#9CB3D2',\n borderMid: '#5273A1',\n /** Primary/300 — supporting/helper text on blue-tinted UI */\n p300: '#809BBF',\n /** Indigo/300 — \"Set to now\" link color */\n linkBlue: '#3C5BD5',\n} as const;\n\n// ─── Interactive states ───────────────────────────────────────────────────────\n\nexport const interactive = {\n /** Active / focused border */\n activeBorder: oePrimary.fgLow, // #5273A1\n /** Hover border */\n hoverBorder: '#3B82F6',\n /** Focus ring shadow */\n focusRing: '#D7DFEA',\n /** Invalid border */\n invalidBorder: status.error,\n} as const;\n\n// ─── Padding tokens (PD) ─────────────────────────────────────────────────────\n\nexport const padding = {\n 'PD-0': 0,\n 'PD-1': 1,\n 'PD-2': 2,\n 'PD-3': 4,\n 'PD-4': 6,\n 'PD-5': 8,\n 'PD-6': 12,\n 'PD-7': 16,\n 'PD-8': 24,\n 'PD-9': 32,\n 'PD-10': 40,\n 'PD-11': 48,\n 'PD-12': 56,\n 'PD-13': 64,\n 'PD-14': 72,\n 'PD-15': 80,\n} as const;\n\n// ─── Corner Radius tokens (CR) ───────────────────────────────────────────────\n\nexport const radius = {\n 'CR-0': 0,\n 'CR-1': 2,\n 'CR-2': 4,\n 'CR-3': 8,\n 'CR-4': 12,\n 'CR-5': 16,\n 'CR-6': 20,\n 'CR-7': 24,\n 'CR-8': 32,\n 'CR-9': 48,\n 'CR-10': 100,\n} as const;\n\n// ─── Typography ───────────────────────────────────────────────────────────────\n\nexport const font = 'Sarabun, sans-serif';\n","import React from 'react';\nimport { Circle, Info, XCircle, Search, Eye } from 'lucide-react';\nimport { grayNeutral, status, interactive, font } from './tokens';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type InputFieldState =\n | 'Idle'\n | 'Idle hover'\n | 'Active'\n | 'Idle invalid'\n | 'Idle invalid hover'\n | 'Idle invalid active'\n | 'Filled'\n | 'Filled hover'\n | 'Filled active'\n | 'Filled invalid'\n | 'Filled invalid hover'\n | 'Filled invalid active'\n | 'Disable'\n | 'Keyboard focus'\n | 'Skeleton';\n\nexport type InputFieldSize = 'sm' | 'md' | 'lg';\n\nexport type InputFieldTrailingIcon = 'clear' | 'password' | 'search';\n\nexport type InputFieldCounter = {\n value: number;\n max: number;\n};\n\nexport interface InputFieldProps {\n /** Label text displayed above the input */\n label: string;\n /** Show required asterisk (*) */\n required?: boolean;\n /** Remark text next to label e.g. \"(optional)\" */\n labelRemark?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Current value */\n value?: string;\n /** Called when value changes */\n onChange?: (value: string) => void;\n /** Helper text below the input (hidden when invalid) */\n helperText?: string;\n /** Error message below the input (shown when invalid state) */\n errorText?: string;\n /** Visual state from Figma */\n state?: InputFieldState;\n /** Input size — affects height, font, and padding */\n size?: InputFieldSize;\n /** Leading dropdown prefix text */\n leadingDropdownText?: string;\n /**\n * Leading icon inside the input (left side).\n * - `true` → default Circle icon\n * - `React.ElementType` → custom Lucide icon\n * - `false/undefined` → no icon\n */\n leadingIcon?: React.ElementType | boolean;\n /** Counter pill e.g. `{ value: 0, max: 20 }` */\n counter?: InputFieldCounter;\n /** Unit text inside the input */\n unit?: string;\n /** Single trailing icon */\n trailingIcon?: InputFieldTrailingIcon;\n /** Multiple trailing icons (overrides trailingIcon) */\n trailingIcons?: InputFieldTrailingIcon[];\n /** Show separator between trailing icons */\n trailingIconSeparator?: boolean;\n}\n\n// ─── Design tokens (from Figma) ──────────────────────────────────────────────\n\n/**\n * Size tokens — matched to Figma nodes:\n * sm (Sm-32): label C5 12/18 · input C4 14/20 · helper C5 12/18\n * md (Md-40): label C4 14/20 · input C3 16/24 · helper C4 14/20\n * lg (Lg-48): label C3 16/24 · input C3 16/24 · helper C4 14/20\n *\n * Spacing (per Figma sm node — gap-4 between all elements):\n * labelGap = gap between label row and input box\n * helperGap = gap between input box and helper/error text\n */\nconst sizeTokens = {\n sm: {\n inputHeight: 32,\n labelFontSize: 12, labelLineHeight: 18,\n inputFontSize: 14, inputLineHeight: 20,\n helperFontSize: 12, helperLineHeight: 18,\n paddingX: 12,\n iconSize: 16,\n labelIconSize: 12,\n labelGap: 4, // label row → input\n helperGap: 4, // input → helper text\n leadingPl: 8, leadingPr: 4, leadingPy: 6,\n chevronSize: 14,\n counterPadding: '1px 4px',\n counterRadius: 4,\n counterFontSize: 12, counterLineHeight: 18,\n skeletonLabelH: 18, skeletonInputH: 32,\n },\n md: {\n inputHeight: 40,\n labelFontSize: 14, labelLineHeight: 20,\n inputFontSize: 16, inputLineHeight: 24,\n helperFontSize: 14, helperLineHeight: 20,\n paddingX: 16,\n iconSize: 20,\n labelIconSize: 14,\n labelGap: 6, // label row → input\n helperGap: 4, // input → helper text\n leadingPl: 12, leadingPr: 8, leadingPy: 8,\n chevronSize: 16,\n counterPadding: '2px 8px',\n counterRadius: 8,\n counterFontSize: 14, counterLineHeight: 20,\n skeletonLabelH: 20, skeletonInputH: 40,\n },\n lg: {\n inputHeight: 48,\n labelFontSize: 16, labelLineHeight: 24,\n inputFontSize: 16, inputLineHeight: 24,\n helperFontSize: 14, helperLineHeight: 20,\n paddingX: 16,\n iconSize: 20,\n labelIconSize: 16,\n labelGap: 8, // label row → input\n helperGap: 6, // input → helper text\n leadingPl: 16, leadingPr: 8, leadingPy: 12,\n chevronSize: 16,\n counterPadding: '2px 8px',\n counterRadius: 8,\n counterFontSize: 14, counterLineHeight: 20,\n skeletonLabelH: 24, skeletonInputH: 48,\n },\n} as const;\n\n// ─── State helpers ────────────────────────────────────────────────────────────\n\nconst focusRingStyle = `0 0 0 2px ${interactive.focusRing}`;\n\nconst getStateFlags = (state: InputFieldState | undefined) => {\n const s = state ?? 'Idle';\n const isInvalid = s.includes('invalid');\n const isHover = s.includes('hover');\n const isActive = s === 'Active' || s === 'Keyboard focus' || s.endsWith('active');\n const isDisabled = s === 'Disable';\n const isSkeleton = s === 'Skeleton';\n const isFilled = s.includes('Filled');\n const isKeyboardFocus = s === 'Keyboard focus';\n return { s, isInvalid, isHover, isActive, isDisabled, isSkeleton, isFilled, isKeyboardFocus };\n};\n\n// ─── Trailing icon map → Lucide ───────────────────────────────────────────────\n\nconst TRAILING_ICON_MAP = {\n clear: XCircle,\n search: Search,\n password: Eye,\n} as const;\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport const InputField = ({\n label,\n required = false,\n labelRemark,\n placeholder = 'Placeholder',\n value,\n onChange: _onChange,\n helperText,\n errorText,\n state = 'Idle',\n size = 'md',\n leadingDropdownText,\n leadingIcon,\n counter,\n unit,\n trailingIcon,\n trailingIcons,\n trailingIconSeparator = false,\n}: InputFieldProps) => {\n const { isInvalid, isHover, isActive, isDisabled, isSkeleton, isKeyboardFocus } =\n getStateFlags(state);\n\n const t = sizeTokens[size];\n\n // ── Colors — mapped to Semantic/Gray-Neutral tokens ─────────────────────\n const borderColor = isInvalid\n ? interactive.invalidBorder // status.error #DB1439\n : isActive || isKeyboardFocus\n ? interactive.activeBorder // oePrimary.fgLow #5273A1\n : isHover\n ? interactive.hoverBorder // #3B82F6\n : grayNeutral.borderMidgray; // #CFD1D9\n\n const background = isDisabled\n ? grayNeutral.bgDisabled // #F3F4F6\n : isHover\n ? grayNeutral.bgLightgray // #F8F8F9\n : grayNeutral.bgWhite; // #FFFFFF\n\n // Label text → fg/mid-on-white (disabled → fg/low)\n const labelColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgMid;\n\n // Placeholder → fg/low-on-white (same whether disabled or not)\n const placeholderColor = grayNeutral.fgLow; // #9A9DAD\n\n // Typed value → fg/high (disabled → fg/low)\n const valueColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgHigh; // #1B1D22\n\n // ── Icon colors (Figma: Semantic/Gray-Neutral/fg/high for input icons) ───\n // Input leading/trailing icons → fg/high (#1B1D22)\n const inputIconColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgHigh;\n // Label info icon → fg/mid (same as label text, #6A6E83)\n const labelIconColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgMid;\n\n const helperColor = isInvalid ? status.error : grayNeutral.fgMid; // #6A6E83\n\n // ── Skeleton ─────────────────────────────────────────────────────────────\n if (isSkeleton) {\n return (\n <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: t.labelGap }}>\n <div style={{ height: t.skeletonLabelH, background: grayNeutral.bgSkeleton, borderRadius: 6 }} />\n <div style={{ height: t.skeletonInputH, background: grayNeutral.bgSkeleton, border: `1px solid ${grayNeutral.bgSkeleton}`, borderRadius: 24 }} />\n </div>\n );\n }\n\n // ── Leading icon resolve ──────────────────────────────────────────────────\n // true → Circle (Figma default \"Icon/circle\"), component → custom, false → none\n const LeadingIconComponent: React.ElementType | null =\n leadingIcon === true\n ? Circle\n : leadingIcon\n ? (leadingIcon as React.ElementType)\n : null;\n\n // ── Trailing icons ────────────────────────────────────────────────────────\n const iconsToRender: InputFieldTrailingIcon[] =\n trailingIcons?.length ? trailingIcons : trailingIcon ? [trailingIcon] : [];\n\n // ── Text below input ──────────────────────────────────────────────────────\n const showText = isInvalid ? errorText : helperText;\n\n // ── Shared font style ─────────────────────────────────────────────────────\n const baseFont: React.CSSProperties = { fontFamily: font, fontWeight: 500 };\n\n return (\n /*\n * Outer wrapper — two-level gap structure matching Figma:\n * Level 1 (helperGap): separates [label + input block] from [helper text]\n * Level 2 (labelGap): separates [label row] from [input box]\n */\n <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: t.helperGap }}>\n\n {/* ── Level 1: label + input block ────────────────────────────────── */}\n <div style={{ display: 'flex', flexDirection: 'column', gap: t.labelGap, width: '100%' }}>\n\n {/* Label row */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, width: '100%' }}>\n {/* Left: label text + info icon */}\n <div style={{ display: 'flex', flex: '1 0 0', alignItems: 'center', gap: t.labelIconSize === 12 ? 4 : 6, minWidth: 0 }}>\n <span\n style={{\n ...baseFont,\n fontSize: t.labelFontSize,\n lineHeight: `${t.labelLineHeight}px`,\n color: labelColor,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {label}\n </span>\n {/* Info icon — fg/mid-on-white (same shade as label text) */}\n <Info\n size={t.labelIconSize}\n color={labelIconColor}\n strokeWidth={1.8}\n style={{ flexShrink: 0 }}\n />\n </div>\n\n {/* Right: remark or required marker */}\n {labelRemark && (\n <span\n style={{\n ...baseFont,\n fontSize: t.labelFontSize,\n lineHeight: `${t.labelLineHeight}px`,\n color: labelColor,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n }}\n >\n {labelRemark}\n </span>\n )}\n {required && (\n <span style={{ color: status.error, fontWeight: 800, flexShrink: 0 }}>*</span>\n )}\n </div>\n\n {/* Input box */}\n <div\n style={{\n background,\n border: `1px solid ${borderColor}`,\n height: t.inputHeight,\n width: '100%',\n borderRadius: 24,\n display: 'flex',\n alignItems: leadingDropdownText ? 'stretch' : 'center',\n ...(leadingDropdownText ? {} : { gap: 8, padding: `0 ${t.paddingX}px` }),\n overflow: 'hidden',\n boxShadow: isActive || isKeyboardFocus ? focusRingStyle : 'none',\n opacity: isDisabled ? 0.7 : 1,\n boxSizing: 'border-box',\n }}\n >\n {/* Leading: dropdown prefix OR icon */}\n {leadingDropdownText ? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n background: grayNeutral.bgWhite,\n padding: `${t.leadingPy}px ${t.leadingPr}px ${t.leadingPy}px ${t.leadingPl}px`,\n flexShrink: 0,\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: grayNeutral.fgHigh,\n whiteSpace: 'nowrap',\n }}\n >\n {leadingDropdownText}\n </span>\n <svg width={t.chevronSize} height={t.chevronSize} viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6L8 10L12 6\" stroke={grayNeutral.fgHigh} strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </div>\n ) : LeadingIconComponent ? (\n /* Leading icon in input → fg/high (#1B1D22) per Figma */\n <LeadingIconComponent\n size={t.iconSize}\n color={inputIconColor}\n strokeWidth={1.6}\n style={{ flexShrink: 0 }}\n />\n ) : null}\n\n {/* Text + accessories area */}\n <div\n style={{\n flex: '1 0 0',\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n height: '100%',\n minWidth: 0,\n ...(leadingDropdownText\n ? { borderLeft: `1px solid ${grayNeutral.borderLight}`, padding: `0 12px` }\n : {}),\n }}\n >\n {/* Placeholder / Value text */}\n <div\n style={{\n flex: '1 0 0',\n overflow: 'hidden',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: value ? valueColor : placeholderColor,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n display: 'block',\n width: '100%',\n }}\n >\n {value || placeholder}\n </span>\n </div>\n\n {/* Counter pill */}\n {counter && (\n <div\n style={{\n background: grayNeutral.bgLightgray,\n display: 'flex',\n gap: 2,\n alignItems: 'center',\n justifyContent: 'center',\n padding: t.counterPadding,\n borderRadius: t.counterRadius,\n flexShrink: 0,\n opacity: isDisabled ? 0.7 : 1,\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.counterFontSize,\n lineHeight: `${t.counterLineHeight}px`,\n color: grayNeutral.fgHigh,\n }}\n >\n {counter.value}\n </span>\n <span\n style={{\n ...baseFont,\n fontSize: t.counterFontSize,\n lineHeight: `${t.counterLineHeight}px`,\n color: grayNeutral.fgMid,\n }}\n >\n / {counter.max}\n </span>\n </div>\n )}\n\n {/* Unit text */}\n {unit && (\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: grayNeutral.fgHigh,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n maxWidth: 64,\n overflow: 'hidden',\n }}\n >\n {unit}\n </span>\n )}\n\n {/* Trailing icons */}\n {iconsToRender.length > 0 && (\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, flexShrink: 0 }}>\n {iconsToRender.map((ic, idx) => {\n const TrailingIcon = TRAILING_ICON_MAP[ic];\n return (\n <React.Fragment key={`${ic}-${idx}`}>\n {trailingIconSeparator && idx > 0 && (\n <div\n style={{\n width: 1,\n height: t.iconSize,\n background: grayNeutral.gray300,\n flexShrink: 0,\n alignSelf: 'center',\n }}\n />\n )}\n {/* Trailing icon → fg/high (#1B1D22) per Figma */}\n <TrailingIcon\n size={t.iconSize}\n color={inputIconColor}\n strokeWidth={1.6}\n style={{ flexShrink: 0 }}\n />\n </React.Fragment>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* ── Level 1: helper / error text ────────────────────────────────── */}\n {/*\n * No extra margin here — the outer helperGap (4px sm / 4px md / 6px lg)\n * from the flex container already provides the correct spacing from Figma.\n */}\n {showText && (\n <p\n style={{\n ...baseFont,\n margin: 0,\n fontSize: t.helperFontSize,\n lineHeight: `${t.helperLineHeight}px`,\n color: helperColor,\n width: '100%',\n }}\n >\n {showText}\n </p>\n )}\n </div>\n );\n};\n","// ─── Senestia Design System — Public API ─────────────────────────────────────\n//\n// import { Badge, InputField, tokens } from '@senestia/ui'\n//\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ── Components ────────────────────────────────────────────────────────────────\nexport { Badge } from './stories/Badge';\nexport { InputField } from './stories/InputField';\n\n// ── Component types ───────────────────────────────────────────────────────────\nexport type { BadgeProps, BadgeColor, BadgeSize, BadgeType } from './stories/Badge';\nexport type {\n InputFieldProps,\n InputFieldState,\n InputFieldSize,\n InputFieldTrailingIcon,\n InputFieldCounter,\n} from './stories/InputField';\n\n// ── Design Tokens ─────────────────────────────────────────────────────────────\nexport {\n // Colors\n grayNeutral,\n status,\n ciPrimary,\n oePrimary,\n interactive,\n // Spacing\n padding,\n radius,\n // Typography\n font,\n} from './stories/tokens';\n\n// ── Tokens namespace (for tree-shaking friendly usage) ────────────────────────\nimport * as _tokens from './stories/tokens';\nexport const tokens = _tokens;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"senestia-ui.umd.js","names":[],"sources":["../src/stories/Badge.tsx","../src/stories/tokens.ts","../src/stories/InputField.tsx","../src/index.ts"],"sourcesContent":["import React from 'react';\nimport { X } from 'lucide-react';\n\n// ─── Design System Font ──────────────────────────────────────────────────────\nconst font = 'Sarabun, sans-serif';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type BadgeColor =\n | 'Gray'\n | 'Primary'\n | 'Error'\n | 'Warning'\n | 'Success'\n | 'Blue light'\n | 'Blue'\n | 'Indigo'\n | 'Purple'\n | 'Pink'\n | 'Orange'\n | 'Gray blue';\n\nexport type BadgeSize = 'sm' | 'md' | 'lg';\n\nexport type BadgeType = 'Idle' | 'Status Dot' | 'Closable' | 'Pill color';\n\nexport interface BadgeProps {\n /** Badge label text */\n label?: string;\n /** Color variant */\n color?: BadgeColor;\n /** Size variant */\n size?: BadgeSize;\n /** Type / style variant */\n type?: BadgeType;\n /** Icon to render inside Pill color type (Lucide icon component) */\n icon?: React.ElementType;\n /** Called when close button is clicked (Closable type) */\n onClose?: () => void;\n}\n\n// ─── Color Tokens ────────────────────────────────────────────────────────────\n\nconst COLOR_TOKENS: Record<\n BadgeColor,\n { bg: string; border: string; text: string; dot: string }\n> = {\n Gray: { bg: '#f9fafb', border: '#eaecf0', text: '#06080b', dot: '#667085' },\n Primary: { bg: '#f4f6f9', border: '#e6ebf2', text: '#1e2b3b', dot: '#6c8fbe' },\n Error: { bg: '#fef0ef', border: '#fbd2d0', text: '#cc1a11', dot: '#f04438' },\n Warning: { bg: '#fff9ee', border: '#ffedcc', text: '#db8f02', dot: '#f79009' },\n Success: { bg: '#f0fdfa', border: '#d2f9f1', text: '#15a686', dot: '#12b76a' },\n 'Blue light': { bg: '#f0f9ff', border: '#b9e6fe', text: '#026aa2', dot: '#0ba5ec' },\n Blue: { bg: '#eff8ff', border: '#b2ddff', text: '#175cd3', dot: '#2e90fa' },\n Indigo: { bg: '#eef4ff', border: '#c7d7fe', text: '#3538cd', dot: '#6172f3' },\n Purple: { bg: '#f4f3ff', border: '#d9d6fe', text: '#5925dc', dot: '#7a5af8' },\n Pink: { bg: '#fef6fb', border: '#fce7f6', text: '#c11574', dot: '#ee46bc' },\n Orange: { bg: '#fef6ee', border: '#ffd6ae', text: '#b93815', dot: '#ef6820' },\n 'Gray blue':{ bg: '#f8f9fc', border: '#d5d9eb', text: '#363f72', dot: '#717bbc' },\n};\n\n// ─── Size Tokens ─────────────────────────────────────────────────────────────\n\nconst SIZE_TOKENS: Record<\n BadgeSize,\n {\n paddingX: number;\n paddingY: number;\n paddingXClose: { left: number; right: number };\n paddingXDot: { left: number; right: number };\n paddingPill: number;\n fontSize: number;\n lineHeight: number;\n dotSize: number;\n iconSize: number;\n closeSize: number;\n }\n> = {\n sm: {\n paddingX: 8, paddingY: 2,\n paddingXClose: { left: 8, right: 4 },\n paddingXDot: { left: 6, right: 8 },\n paddingPill: 5,\n fontSize: 12, lineHeight: 18,\n dotSize: 6, iconSize: 12, closeSize: 12,\n },\n md: {\n paddingX: 8, paddingY: 2,\n paddingXClose: { left: 8, right: 4 },\n paddingXDot: { left: 6, right: 8 },\n paddingPill: 6,\n fontSize: 14, lineHeight: 20,\n dotSize: 6, iconSize: 14, closeSize: 14,\n },\n lg: {\n paddingX: 12, paddingY: 4,\n paddingXClose: { left: 12, right: 6 },\n paddingXDot: { left: 8, right: 12 },\n paddingPill: 8,\n fontSize: 14, lineHeight: 20,\n dotSize: 8, iconSize: 16, closeSize: 16,\n },\n};\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport const Badge: React.FC<BadgeProps> = ({\n label = 'Label',\n color = 'Gray',\n size = 'sm',\n type = 'Idle',\n icon: IconComponent,\n onClose,\n}) => {\n const c = COLOR_TOKENS[color];\n const s = SIZE_TOKENS[size];\n\n // ── Shared wrapper style ──────────────────────────────────────────────────\n const baseWrapper: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n backgroundColor: c.bg,\n border: `1px solid ${c.border}`,\n borderRadius: 16,\n boxSizing: 'border-box',\n width: 'fit-content',\n fontFamily: font,\n };\n\n // ── Text style ────────────────────────────────────────────────────────────\n const textStyle: React.CSSProperties = {\n fontSize: s.fontSize,\n lineHeight: `${s.lineHeight}px`,\n fontWeight: 500,\n color: c.text,\n whiteSpace: 'nowrap',\n fontFamily: font,\n margin: 0,\n };\n\n // ── Idle ─────────────────────────────────────────────────────────────────\n if (type === 'Idle') {\n return (\n <span\n style={{\n ...baseWrapper,\n padding: `${s.paddingY}px ${s.paddingX}px`,\n }}\n >\n <span style={textStyle}>{label}</span>\n </span>\n );\n }\n\n // ── Status Dot ────────────────────────────────────────────────────────────\n if (type === 'Status Dot') {\n return (\n <span\n style={{\n ...baseWrapper,\n gap: 4,\n paddingTop: s.paddingY,\n paddingBottom: s.paddingY,\n paddingLeft: s.paddingXDot.left,\n paddingRight: s.paddingXDot.right,\n }}\n >\n {/* Dot */}\n <span\n style={{\n display: 'inline-block',\n width: s.dotSize,\n height: s.dotSize,\n borderRadius: '50%',\n backgroundColor: c.dot,\n flexShrink: 0,\n }}\n />\n <span style={textStyle}>{label}</span>\n </span>\n );\n }\n\n // ── Closable ──────────────────────────────────────────────────────────────\n if (type === 'Closable') {\n return (\n <span\n style={{\n ...baseWrapper,\n gap: 2,\n paddingTop: s.paddingY,\n paddingBottom: s.paddingY,\n paddingLeft: s.paddingXClose.left,\n paddingRight: s.paddingXClose.right,\n }}\n >\n <span style={textStyle}>{label}</span>\n <button\n onClick={onClose}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'none',\n border: 'none',\n padding: 2,\n borderRadius: 3,\n cursor: 'pointer',\n color: c.text,\n flexShrink: 0,\n lineHeight: 1,\n }}\n aria-label=\"Remove\"\n >\n <X size={s.closeSize} strokeWidth={2.5} />\n </button>\n </span>\n );\n }\n\n // ── Pill color (icon only) ────────────────────────────────────────────────\n if (type === 'Pill color') {\n const PillIcon = IconComponent;\n return (\n <span\n style={{\n ...baseWrapper,\n padding: s.paddingPill,\n }}\n >\n {PillIcon ? (\n <PillIcon size={s.iconSize} color={c.dot} strokeWidth={2} />\n ) : (\n // Default: colored circle dot\n <span\n style={{\n display: 'inline-block',\n width: s.iconSize,\n height: s.iconSize,\n borderRadius: '50%',\n backgroundColor: c.dot,\n }}\n />\n )}\n </span>\n );\n }\n\n return null;\n};\n","/**\n * Senestia Design System — Semantic Color Tokens\n *\n * ┌─────────────────────────────────────────────────────────────┐\n * │ Source: Figma DS-01 · Foundation → Semantic Color │\n * │ Use these tokens in components instead of raw hex values. │\n * └─────────────────────────────────────────────────────────────┘\n */\n\n// ─── Gray-Neutral ─────────────────────────────────────────────────────────────\n\nexport const grayNeutral = {\n /** Semantic/Gray-Neutral/fg/high — primary text, dark icons */\n fgHigh: '#1B1D22',\n /** Semantic/Gray-Neutral/fg/mid-on-white — label text, helper text, secondary icons */\n fgMid: '#6A6E83',\n /** Semantic/Gray-Neutral/fg/low-on-white — placeholder, disabled text */\n fgLow: '#9A9DAD',\n\n /** Semantic/Gray-Neutral/bg/white */\n bgWhite: '#FFFFFF',\n /** Semantic/Gray-Neutral/bg/lightgray — counter pill, subtle backgrounds */\n bgLightgray: '#F8F8F9',\n /** Semantic/Gray-Neutral/bg/disabled */\n bgDisabled: '#F3F4F6',\n\n /** Semantic/Gray-Neutral/border/midgray — default input border */\n borderMidgray: '#CFD1D9',\n /** Semantic/Gray-Neutral/border/light — dividers, card borders */\n borderLight: '#EBECEF',\n /** Disabled border (checkbox, input) */\n borderDisabled: '#E5EAF1',\n\n /** Gray/300 — icon separators */\n gray300: '#D0D5DD',\n /** Skeleton loading shimmer */\n bgSkeleton: '#EEF0F3',\n /** Strong disabled background (checkbox) */\n bgDisabledStrong: '#EBECEF',\n} as const;\n\n// ─── Status ───────────────────────────────────────────────────────────────────\n\nexport const status = {\n /** Error / invalid state */\n error: '#DB1439',\n /** Warning */\n warning: '#DB8F02',\n /** Success */\n success: '#15A686',\n} as const;\n\n// ─── CI Primary (Senestia brand purple) ───────────────────────────────────────\n\nexport const ciPrimary = {\n fgLow: '#C4B3F6',\n fgHigh: '#802CEB',\n bgLow: '#D4C9F6',\n bgMid: '#802CEB',\n bgHigh: '#5A1DA9',\n borderMid: '#996CF3',\n borderHigh: '#802CEB',\n} as const;\n\n// ─── OE Theme (OE brand blue) ─────────────────────────────────────────────────\n\nexport const oePrimary = {\n fgLow: '#5273A1',\n fgHigh: '#3A5274',\n bgLowest: '#EFF2F6', // selected item background in pickers\n bgLow: '#6E90BF',\n bgMid: '#5273A1',\n bgHigh: '#3A5274',\n borderLowest:'#C6D2E3', // focused item border\n borderLow: '#9CB3D2',\n borderMid: '#5273A1',\n /** Primary/300 — supporting/helper text on blue-tinted UI */\n p300: '#809BBF',\n /** Indigo/300 — \"Set to now\" link color */\n linkBlue: '#3C5BD5',\n} as const;\n\n// ─── Interactive states ───────────────────────────────────────────────────────\n\nexport const interactive = {\n /** Active / focused border */\n activeBorder: oePrimary.fgLow, // #5273A1\n /** Hover border */\n hoverBorder: '#3B82F6',\n /** Focus ring shadow */\n focusRing: '#D7DFEA',\n /** Invalid border */\n invalidBorder: status.error,\n} as const;\n\n// ─── Padding tokens (PD) ─────────────────────────────────────────────────────\n\nexport const padding = {\n 'PD-0': 0,\n 'PD-1': 1,\n 'PD-2': 2,\n 'PD-3': 4,\n 'PD-4': 6,\n 'PD-5': 8,\n 'PD-6': 12,\n 'PD-7': 16,\n 'PD-8': 24,\n 'PD-9': 32,\n 'PD-10': 40,\n 'PD-11': 48,\n 'PD-12': 56,\n 'PD-13': 64,\n 'PD-14': 72,\n 'PD-15': 80,\n} as const;\n\n// ─── Corner Radius tokens (CR) ───────────────────────────────────────────────\n\nexport const radius = {\n 'CR-0': 0,\n 'CR-1': 2,\n 'CR-2': 4,\n 'CR-3': 8,\n 'CR-4': 12,\n 'CR-5': 16,\n 'CR-6': 20,\n 'CR-7': 24,\n 'CR-8': 32,\n 'CR-9': 48,\n 'CR-10': 100,\n} as const;\n\n// ─── Typography ───────────────────────────────────────────────────────────────\n\nexport const font = 'Sarabun, sans-serif';\n","import React from 'react';\nimport { Circle, Info, XCircle, Search, Eye } from 'lucide-react';\nimport { grayNeutral, status, interactive, font } from './tokens';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type InputFieldState =\n | 'Idle'\n | 'Idle hover'\n | 'Active'\n | 'Idle invalid'\n | 'Idle invalid hover'\n | 'Idle invalid active'\n | 'Filled'\n | 'Filled hover'\n | 'Filled active'\n | 'Filled invalid'\n | 'Filled invalid hover'\n | 'Filled invalid active'\n | 'Disable'\n | 'Keyboard focus'\n | 'Skeleton';\n\nexport type InputFieldSize = 'sm' | 'md' | 'lg';\n\nexport type InputFieldTrailingIcon = 'clear' | 'password' | 'search';\n\nexport type InputFieldCounter = {\n value: number;\n max: number;\n};\n\nexport interface InputFieldProps {\n /** Label text displayed above the input */\n label: string;\n /** Show required asterisk (*) */\n required?: boolean;\n /** Remark text next to label e.g. \"(optional)\" */\n labelRemark?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Current value */\n value?: string;\n /** Called when value changes */\n onChange?: (value: string) => void;\n /** Helper text below the input (hidden when invalid) */\n helperText?: string;\n /** Error message below the input (shown when invalid state) */\n errorText?: string;\n /** Visual state from Figma */\n state?: InputFieldState;\n /** Input size — affects height, font, and padding */\n size?: InputFieldSize;\n /** Leading dropdown prefix text */\n leadingDropdownText?: string;\n /**\n * Leading icon inside the input (left side).\n * - `true` → default Circle icon\n * - `React.ElementType` → custom Lucide icon\n * - `false/undefined` → no icon\n */\n leadingIcon?: React.ElementType | boolean;\n /** Counter pill e.g. `{ value: 0, max: 20 }` */\n counter?: InputFieldCounter;\n /** Unit text inside the input */\n unit?: string;\n /** Single trailing icon */\n trailingIcon?: InputFieldTrailingIcon;\n /** Multiple trailing icons (overrides trailingIcon) */\n trailingIcons?: InputFieldTrailingIcon[];\n /** Show separator between trailing icons */\n trailingIconSeparator?: boolean;\n}\n\n// ─── Design tokens (from Figma) ──────────────────────────────────────────────\n\n/**\n * Size tokens — matched to Figma nodes:\n * sm (Sm-32): label C5 12/18 · input C4 14/20 · helper C5 12/18\n * md (Md-40): label C4 14/20 · input C3 16/24 · helper C4 14/20\n * lg (Lg-48): label C3 16/24 · input C3 16/24 · helper C4 14/20\n *\n * Spacing (per Figma sm node — gap-4 between all elements):\n * labelGap = gap between label row and input box\n * helperGap = gap between input box and helper/error text\n */\nconst sizeTokens = {\n sm: {\n inputHeight: 32,\n labelFontSize: 12, labelLineHeight: 18,\n inputFontSize: 14, inputLineHeight: 20,\n helperFontSize: 12, helperLineHeight: 18,\n paddingX: 12,\n iconSize: 16,\n labelIconSize: 12,\n labelGap: 4, // label row → input\n helperGap: 4, // input → helper text\n leadingPl: 8, leadingPr: 4, leadingPy: 6,\n chevronSize: 14,\n counterPadding: '1px 4px',\n counterRadius: 4,\n counterFontSize: 12, counterLineHeight: 18,\n skeletonLabelH: 18, skeletonInputH: 32,\n },\n md: {\n inputHeight: 40,\n labelFontSize: 14, labelLineHeight: 20,\n inputFontSize: 16, inputLineHeight: 24,\n helperFontSize: 14, helperLineHeight: 20,\n paddingX: 16,\n iconSize: 20,\n labelIconSize: 14,\n labelGap: 6, // label row → input\n helperGap: 4, // input → helper text\n leadingPl: 12, leadingPr: 8, leadingPy: 8,\n chevronSize: 16,\n counterPadding: '2px 8px',\n counterRadius: 8,\n counterFontSize: 14, counterLineHeight: 20,\n skeletonLabelH: 20, skeletonInputH: 40,\n },\n lg: {\n inputHeight: 48,\n labelFontSize: 16, labelLineHeight: 24,\n inputFontSize: 16, inputLineHeight: 24,\n helperFontSize: 14, helperLineHeight: 20,\n paddingX: 16,\n iconSize: 20,\n labelIconSize: 16,\n labelGap: 8, // label row → input\n helperGap: 6, // input → helper text\n leadingPl: 16, leadingPr: 8, leadingPy: 12,\n chevronSize: 16,\n counterPadding: '2px 8px',\n counterRadius: 8,\n counterFontSize: 14, counterLineHeight: 20,\n skeletonLabelH: 24, skeletonInputH: 48,\n },\n} as const;\n\n// ─── State helpers ────────────────────────────────────────────────────────────\n\nconst focusRingStyle = `0 0 0 2px ${interactive.focusRing}`;\n\nconst getStateFlags = (state: InputFieldState | undefined) => {\n const s = state ?? 'Idle';\n const isInvalid = s.includes('invalid');\n const isHover = s.includes('hover');\n const isActive = s === 'Active' || s === 'Keyboard focus' || s.endsWith('active');\n const isDisabled = s === 'Disable';\n const isSkeleton = s === 'Skeleton';\n const isFilled = s.includes('Filled');\n const isKeyboardFocus = s === 'Keyboard focus';\n return { s, isInvalid, isHover, isActive, isDisabled, isSkeleton, isFilled, isKeyboardFocus };\n};\n\n// ─── Trailing icon map → Lucide ───────────────────────────────────────────────\n\nconst TRAILING_ICON_MAP = {\n clear: XCircle,\n search: Search,\n password: Eye,\n} as const;\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport const InputField = ({\n label,\n required = false,\n labelRemark,\n placeholder = 'Placeholder',\n value,\n onChange: _onChange,\n helperText,\n errorText,\n state = 'Idle',\n size = 'md',\n leadingDropdownText,\n leadingIcon,\n counter,\n unit,\n trailingIcon,\n trailingIcons,\n trailingIconSeparator = false,\n}: InputFieldProps) => {\n const { isInvalid, isHover, isActive, isDisabled, isSkeleton, isKeyboardFocus } =\n getStateFlags(state);\n\n const t = sizeTokens[size];\n\n // ── Colors — mapped to Semantic/Gray-Neutral tokens ─────────────────────\n const borderColor = isInvalid\n ? interactive.invalidBorder // status.error #DB1439\n : isActive || isKeyboardFocus\n ? interactive.activeBorder // oePrimary.fgLow #5273A1\n : isHover\n ? interactive.hoverBorder // #3B82F6\n : grayNeutral.borderMidgray; // #CFD1D9\n\n const background = isDisabled\n ? grayNeutral.bgDisabled // #F3F4F6\n : isHover\n ? grayNeutral.bgLightgray // #F8F8F9\n : grayNeutral.bgWhite; // #FFFFFF\n\n // Label text → fg/mid-on-white (disabled → fg/low)\n const labelColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgMid;\n\n // Typed value → fg/high (disabled → fg/low)\n const valueColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgHigh; // #1B1D22\n\n // ── Icon colors (Figma: Semantic/Gray-Neutral/fg/high for input icons) ───\n // Input leading/trailing icons → fg/high (#1B1D22)\n const inputIconColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgHigh;\n // Label info icon → fg/mid (same as label text, #6A6E83)\n const labelIconColor = isDisabled ? grayNeutral.fgLow : grayNeutral.fgMid;\n\n const helperColor = isInvalid ? status.error : grayNeutral.fgMid; // #6A6E83\n\n // ── Skeleton ─────────────────────────────────────────────────────────────\n if (isSkeleton) {\n return (\n <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: t.labelGap }}>\n <div style={{ height: t.skeletonLabelH, background: grayNeutral.bgSkeleton, borderRadius: 6 }} />\n <div style={{ height: t.skeletonInputH, background: grayNeutral.bgSkeleton, border: `1px solid ${grayNeutral.bgSkeleton}`, borderRadius: 24 }} />\n </div>\n );\n }\n\n // ── Leading icon resolve ──────────────────────────────────────────────────\n // true → Circle (Figma default \"Icon/circle\"), component → custom, false → none\n const LeadingIconComponent: React.ElementType | null =\n leadingIcon === true\n ? Circle\n : leadingIcon\n ? (leadingIcon as React.ElementType)\n : null;\n\n // ── Trailing icons ────────────────────────────────────────────────────────\n const iconsToRender: InputFieldTrailingIcon[] =\n trailingIcons?.length ? trailingIcons : trailingIcon ? [trailingIcon] : [];\n\n // ── Text below input ──────────────────────────────────────────────────────\n const showText = isInvalid ? errorText : helperText;\n\n // ── Shared font style ─────────────────────────────────────────────────────\n const baseFont: React.CSSProperties = { fontFamily: font, fontWeight: 500 };\n\n return (\n /*\n * Outer wrapper — two-level gap structure matching Figma:\n * Level 1 (helperGap): separates [label + input block] from [helper text]\n * Level 2 (labelGap): separates [label row] from [input box]\n */\n <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: t.helperGap }}>\n\n {/* ── Level 1: label + input block ────────────────────────────────── */}\n <div style={{ display: 'flex', flexDirection: 'column', gap: t.labelGap, width: '100%' }}>\n\n {/* Label row */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, width: '100%' }}>\n {/* Left: label text + info icon */}\n <div style={{ display: 'flex', flex: '1 0 0', alignItems: 'center', gap: t.labelIconSize === 12 ? 4 : 6, minWidth: 0 }}>\n <span\n style={{\n ...baseFont,\n fontSize: t.labelFontSize,\n lineHeight: `${t.labelLineHeight}px`,\n color: labelColor,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {label}\n </span>\n {/* Info icon — fg/mid-on-white (same shade as label text) */}\n <Info\n size={t.labelIconSize}\n color={labelIconColor}\n strokeWidth={1.8}\n style={{ flexShrink: 0 }}\n />\n </div>\n\n {/* Right: remark or required marker */}\n {labelRemark && (\n <span\n style={{\n ...baseFont,\n fontSize: t.labelFontSize,\n lineHeight: `${t.labelLineHeight}px`,\n color: labelColor,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n }}\n >\n {labelRemark}\n </span>\n )}\n {required && (\n <span style={{ color: status.error, fontWeight: 800, flexShrink: 0 }}>*</span>\n )}\n </div>\n\n {/* Input box */}\n <div\n style={{\n background,\n border: `1px solid ${borderColor}`,\n height: t.inputHeight,\n width: '100%',\n borderRadius: 24,\n display: 'flex',\n alignItems: leadingDropdownText ? 'stretch' : 'center',\n ...(leadingDropdownText ? {} : { gap: 8, padding: `0 ${t.paddingX}px` }),\n overflow: 'hidden',\n boxShadow: isActive || isKeyboardFocus ? focusRingStyle : 'none',\n opacity: isDisabled ? 0.7 : 1,\n boxSizing: 'border-box',\n }}\n >\n {/* Leading: dropdown prefix OR icon */}\n {leadingDropdownText ? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n background: grayNeutral.bgWhite,\n padding: `${t.leadingPy}px ${t.leadingPr}px ${t.leadingPy}px ${t.leadingPl}px`,\n flexShrink: 0,\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: grayNeutral.fgHigh,\n whiteSpace: 'nowrap',\n }}\n >\n {leadingDropdownText}\n </span>\n <svg width={t.chevronSize} height={t.chevronSize} viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6L8 10L12 6\" stroke={grayNeutral.fgHigh} strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </div>\n ) : LeadingIconComponent ? (\n /* Leading icon in input → fg/high (#1B1D22) per Figma */\n <LeadingIconComponent\n size={t.iconSize}\n color={inputIconColor}\n strokeWidth={1.6}\n style={{ flexShrink: 0 }}\n />\n ) : null}\n\n {/* Text + accessories area */}\n <div\n style={{\n flex: '1 0 0',\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n height: '100%',\n minWidth: 0,\n ...(leadingDropdownText\n ? { borderLeft: `1px solid ${grayNeutral.borderLight}`, padding: `0 12px` }\n : {}),\n }}\n >\n {/* Input */}\n <input\n type=\"text\"\n value={value ?? ''}\n onChange={e => _onChange?.(e.target.value)}\n placeholder={placeholder}\n disabled={isDisabled}\n style={{\n ...baseFont,\n flex: '1 0 0',\n border: 'none',\n outline: 'none',\n background: 'transparent',\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: valueColor,\n width: '100%',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n cursor: isDisabled ? 'not-allowed' : 'text',\n }}\n />\n\n {/* Counter pill */}\n {counter && (\n <div\n style={{\n background: grayNeutral.bgLightgray,\n display: 'flex',\n gap: 2,\n alignItems: 'center',\n justifyContent: 'center',\n padding: t.counterPadding,\n borderRadius: t.counterRadius,\n flexShrink: 0,\n opacity: isDisabled ? 0.7 : 1,\n }}\n >\n <span\n style={{\n ...baseFont,\n fontSize: t.counterFontSize,\n lineHeight: `${t.counterLineHeight}px`,\n color: grayNeutral.fgHigh,\n }}\n >\n {counter.value}\n </span>\n <span\n style={{\n ...baseFont,\n fontSize: t.counterFontSize,\n lineHeight: `${t.counterLineHeight}px`,\n color: grayNeutral.fgMid,\n }}\n >\n / {counter.max}\n </span>\n </div>\n )}\n\n {/* Unit text */}\n {unit && (\n <span\n style={{\n ...baseFont,\n fontSize: t.inputFontSize,\n lineHeight: `${t.inputLineHeight}px`,\n color: grayNeutral.fgHigh,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n maxWidth: 64,\n overflow: 'hidden',\n }}\n >\n {unit}\n </span>\n )}\n\n {/* Trailing icons */}\n {iconsToRender.length > 0 && (\n <div style={{ display: 'flex', alignItems: 'center', gap: 4, flexShrink: 0 }}>\n {iconsToRender.map((ic, idx) => {\n const TrailingIcon = TRAILING_ICON_MAP[ic];\n return (\n <React.Fragment key={`${ic}-${idx}`}>\n {trailingIconSeparator && idx > 0 && (\n <div\n style={{\n width: 1,\n height: t.iconSize,\n background: grayNeutral.gray300,\n flexShrink: 0,\n alignSelf: 'center',\n }}\n />\n )}\n {/* Trailing icon → fg/high (#1B1D22) per Figma */}\n <TrailingIcon\n size={t.iconSize}\n color={inputIconColor}\n strokeWidth={1.6}\n style={{ flexShrink: 0 }}\n />\n </React.Fragment>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* ── Level 1: helper / error text ────────────────────────────────── */}\n {/*\n * No extra margin here — the outer helperGap (4px sm / 4px md / 6px lg)\n * from the flex container already provides the correct spacing from Figma.\n */}\n {showText && (\n <p\n style={{\n ...baseFont,\n margin: 0,\n fontSize: t.helperFontSize,\n lineHeight: `${t.helperLineHeight}px`,\n color: helperColor,\n width: '100%',\n }}\n >\n {showText}\n </p>\n )}\n </div>\n );\n};\n","// ─── Senestia Design System — Public API ─────────────────────────────────────\n//\n// import { Badge, InputField, tokens } from '@senestia/ui'\n//\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ── Components ────────────────────────────────────────────────────────────────\nexport { Badge } from './stories/Badge';\nexport { InputField } from './stories/InputField';\n\n// ── Component types ───────────────────────────────────────────────────────────\nexport type { BadgeProps, BadgeColor, BadgeSize, BadgeType } from './stories/Badge';\nexport type {\n InputFieldProps,\n InputFieldState,\n InputFieldSize,\n InputFieldTrailingIcon,\n InputFieldCounter,\n} from './stories/InputField';\n\n// ── Design Tokens ─────────────────────────────────────────────────────────────\nexport {\n // Colors\n grayNeutral,\n status,\n ciPrimary,\n oePrimary,\n interactive,\n // Spacing\n padding,\n radius,\n // Typography\n font,\n} from './stories/tokens';\n\n// ── Tokens namespace (for tree-shaking friendly usage) ────────────────────────\nimport * as _tokens from './stories/tokens';\nexport const tokens = _tokens;\n"],"mappings":"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"}
|