@f0rbit/ui 0.1.2 → 0.1.6

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/server.js CHANGED
@@ -471,8 +471,9 @@ function Collapsible(props) {
471
471
  var _tmpl$10 = '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="13 4 6 12 3 9"></polyline></svg>';
472
472
  var _tmpl$29 = ["<div", ">", "</div>"];
473
473
  var _tmpl$34 = ['<div class="step-description">', "</div>"];
474
- var _tmpl$44 = ["<div", '><div class="step-title">', "</div>", "</div>"];
475
- var _tmpl$52 = ["<div", "></div>"];
474
+ var _tmpl$44 = ['<div class="step-body">', "</div>"];
475
+ var _tmpl$52 = ["<div", '><div class="step-title">', "</div>", "", "</div>"];
476
+ var _tmpl$62 = ["<div", "></div>"];
476
477
  var StepperContext = createContext();
477
478
  var statusClasses = {
478
479
  completed: "step-completed",
@@ -484,11 +485,11 @@ function CheckIcon() {
484
485
  }
485
486
  var StepContext = createContext();
486
487
  function Step(props) {
487
- const [local, rest] = splitProps(props, ["title", "description", "icon", "status", "class"]);
488
+ const [local, rest] = splitProps(props, ["title", "description", "icon", "status", "class", "children", "number", "orientation"]);
488
489
  const stepperCtx = useContext(StepperContext);
489
490
  const stepCtx = useContext(StepContext);
490
- const stepNumber = stepperCtx?.registerStep() ?? 1;
491
- const orientation = () => stepCtx?.orientation() ?? "horizontal";
491
+ const stepNumber = local.number ?? stepperCtx?.registerStep() ?? 1;
492
+ const orientation = () => local.orientation ?? stepCtx?.orientation() ?? "vertical";
492
493
  const status = () => local.status ?? "upcoming";
493
494
  const isVertical = () => orientation() === "vertical";
494
495
  const classes = () => {
@@ -535,14 +536,21 @@ function Step(props) {
535
536
  get ["class"]() {
536
537
  return classes();
537
538
  }
538
- }, rest), [ssr(_tmpl$29, ssrAttribute("class", escape(indicatorClasses(), true), false), escape(indicator())), ssr(_tmpl$44, ssrAttribute("class", escape(contentClasses(), true), false), escape(local.title), escape(createComponent(Show, {
539
+ }, rest), [ssr(_tmpl$29, ssrAttribute("class", escape(indicatorClasses(), true), false), escape(indicator())), ssr(_tmpl$52, ssrAttribute("class", escape(contentClasses(), true), false), escape(local.title), escape(createComponent(Show, {
539
540
  get when() {
540
541
  return local.description;
541
542
  },
542
543
  get children() {
543
544
  return ssr(_tmpl$34, escape(local.description));
544
545
  }
545
- }))), ssr(_tmpl$52, ssrAttribute("class", escape(connectorClasses(), true), false))], false);
546
+ })), escape(createComponent(Show, {
547
+ get when() {
548
+ return local.children;
549
+ },
550
+ get children() {
551
+ return ssr(_tmpl$44, escape(local.children));
552
+ }
553
+ }))), ssr(_tmpl$62, ssrAttribute("class", escape(connectorClasses(), true), false))], false);
546
554
  }
547
555
  function Stepper(props) {
548
556
  const [local, rest] = splitProps(props, ["orientation", "class", "children"]);
@@ -576,32 +584,21 @@ function Stepper(props) {
576
584
  }
577
585
  });
578
586
  }
579
- var TabsContext = createContext();
580
587
  function Tabs(props) {
581
- const [local, rest] = splitProps(props, ["defaultValue", "value", "onValueChange", "children", "class"]);
582
- const [internalValue, setInternalValue] = createSignal(local.defaultValue ?? "");
583
- const isControlled = () => local.value !== void 0;
584
- const activeTab = () => isControlled() ? local.value : internalValue();
585
- const setActiveTab = (id) => {
586
- if (!isControlled()) {
587
- setInternalValue(id);
588
- }
589
- local.onValueChange?.(id);
590
- };
588
+ const [local, rest] = splitProps(props, ["defaultValue", "children", "class"]);
589
+ const [activeTab, setActiveTab] = createSignal(local.defaultValue ?? "");
590
+ onMount(() => {
591
+ return;
592
+ });
591
593
  const classes = () => `tabs ${local.class ?? ""}`.trim();
592
- return createComponent(TabsContext.Provider, {
593
- value: {
594
- activeTab,
595
- setActiveTab
594
+ return ssrElement("div", mergeProps({
595
+ get ["class"]() {
596
+ return classes();
596
597
  },
597
- get children() {
598
- return ssrElement("div", mergeProps({
599
- get ["class"]() {
600
- return classes();
601
- }
602
- }, rest), escape(local.children), false);
598
+ get ["data-default-value"]() {
599
+ return local.defaultValue;
603
600
  }
604
- });
601
+ }, rest), escape(local.children), false);
605
602
  }
606
603
  function TabList(props) {
607
604
  const [local, rest] = splitProps(props, ["children", "class"]);
@@ -615,50 +612,33 @@ function TabList(props) {
615
612
  }
616
613
  function Tab(props) {
617
614
  const [local, rest] = splitProps(props, ["value", "children", "class"]);
618
- const ctx = useContext(TabsContext);
619
- const isActive = () => ctx?.activeTab() === local.value;
620
- const classes = () => {
621
- const parts = ["tab"];
622
- if (isActive()) {
623
- parts.push("active");
624
- }
625
- if (local.class) {
626
- parts.push(local.class);
627
- }
628
- return parts.join(" ");
629
- };
615
+ const classes = () => `tab ${local.class ?? ""}`.trim();
630
616
  return ssrElement("button", mergeProps({
631
617
  type: "button",
632
618
  role: "tab",
633
- get ["aria-selected"]() {
634
- return isActive();
635
- },
636
- get tabIndex() {
637
- return isActive() ? 0 : -1;
638
- },
619
+ "aria-selected": "false",
620
+ tabIndex: -1,
639
621
  get ["class"]() {
640
622
  return classes();
623
+ },
624
+ get ["data-tab-value"]() {
625
+ return local.value;
641
626
  }
642
627
  }, rest), escape(local.children), false);
643
628
  }
644
629
  function TabPanel(props) {
645
630
  const [local, rest] = splitProps(props, ["value", "children", "class"]);
646
- const ctx = useContext(TabsContext);
647
- const isActive = () => ctx?.activeTab() === local.value;
648
631
  const classes = () => `tab-panel ${local.class ?? ""}`.trim();
649
- return createComponent(Show, {
650
- get when() {
651
- return isActive();
632
+ return ssrElement("div", mergeProps({
633
+ get ["class"]() {
634
+ return classes();
652
635
  },
653
- get children() {
654
- return ssrElement("div", mergeProps({
655
- get ["class"]() {
656
- return classes();
657
- },
658
- role: "tabpanel"
659
- }, rest), escape(local.children), false);
660
- }
661
- });
636
+ role: "tabpanel",
637
+ get ["data-panel-value"]() {
638
+ return local.value;
639
+ },
640
+ hidden: true
641
+ }, rest), escape(local.children), false);
662
642
  }
663
643
  var _tmpl$11 = ["<label", ">", '<span class="checkbox-box" aria-hidden="true"><svg class="checkbox-check" viewBox="0 0 12 12" fill="none"><path d="M2 6L5 9L10 3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="checkbox-indeterminate"></span></span>', "</label>"];
664
644
  var _tmpl$210 = ['<span class="checkbox-content">', "", "</span>"];
package/dist/server.jsx CHANGED
@@ -445,11 +445,11 @@ function CheckIcon() {
445
445
  }
446
446
  var StepContext = createContext3();
447
447
  function Step(props) {
448
- const [local, rest] = splitProps14(props, ["title", "description", "icon", "status", "class"]);
448
+ const [local, rest] = splitProps14(props, ["title", "description", "icon", "status", "class", "children", "number", "orientation"]);
449
449
  const stepperCtx = useContext3(StepperContext);
450
450
  const stepCtx = useContext3(StepContext);
451
- const stepNumber = stepperCtx?.registerStep() ?? 1;
452
- const orientation = () => stepCtx?.orientation() ?? "horizontal";
451
+ const stepNumber = local.number ?? stepperCtx?.registerStep() ?? 1;
452
+ const orientation = () => local.orientation ?? stepCtx?.orientation() ?? "vertical";
453
453
  const status = () => local.status ?? "upcoming";
454
454
  const isVertical = () => orientation() === "vertical";
455
455
  const classes = () => {
@@ -499,6 +499,9 @@ function Step(props) {
499
499
  <Show5 when={local.description}>
500
500
  <div class="step-description">{local.description}</div>
501
501
  </Show5>
502
+ <Show5 when={local.children}>
503
+ <div class="step-body">{local.children}</div>
504
+ </Show5>
502
505
  </div>
503
506
  <div class={connectorClasses()} />
504
507
  </div>;
@@ -525,25 +528,59 @@ function Stepper(props) {
525
528
  }
526
529
 
527
530
  // src/components/Tabs.tsx
528
- import { splitProps as splitProps15, createSignal as createSignal4, createContext as createContext4, useContext as useContext4, Show as Show6 } from "solid-js";
529
- var TabsContext = createContext4();
531
+ import { splitProps as splitProps15, onMount as onMount3, onCleanup as onCleanup3, createSignal as createSignal4 } from "solid-js";
530
532
  function Tabs(props) {
531
- const [local, rest] = splitProps15(props, ["defaultValue", "value", "onValueChange", "children", "class"]);
532
- const [internalValue, setInternalValue] = createSignal4(local.defaultValue ?? "");
533
- const isControlled = () => local.value !== void 0;
534
- const activeTab = () => isControlled() ? local.value : internalValue();
535
- const setActiveTab = (id) => {
536
- if (!isControlled()) {
537
- setInternalValue(id);
533
+ const [local, rest] = splitProps15(props, ["defaultValue", "children", "class"]);
534
+ let containerRef;
535
+ const [activeTab, setActiveTab] = createSignal4(local.defaultValue ?? "");
536
+ const updateTabs = (value) => {
537
+ if (!containerRef) return;
538
+ const tabs = containerRef.querySelectorAll("[data-tab-value]");
539
+ tabs.forEach((tab) => {
540
+ const isActive = tab.dataset.tabValue === value;
541
+ tab.setAttribute("aria-selected", String(isActive));
542
+ tab.setAttribute("tabindex", isActive ? "0" : "-1");
543
+ tab.classList.toggle("active", isActive);
544
+ });
545
+ const panels = containerRef.querySelectorAll("[data-panel-value]");
546
+ panels.forEach((panel) => {
547
+ const isActive = panel.dataset.panelValue === value;
548
+ panel.hidden = !isActive;
549
+ });
550
+ };
551
+ const initializeTabs = () => {
552
+ if (!containerRef) return;
553
+ let value = activeTab();
554
+ if (!value) {
555
+ const firstTab = containerRef.querySelector("[data-tab-value]");
556
+ value = firstTab?.dataset.tabValue ?? "";
557
+ if (value) setActiveTab(value);
538
558
  }
539
- local.onValueChange?.(id);
559
+ if (value) updateTabs(value);
540
560
  };
561
+ onMount3(() => {
562
+ if (!containerRef) return;
563
+ containerRef.addEventListener("click", (e) => {
564
+ const tab = e.target.closest("[data-tab-value]");
565
+ if (tab?.dataset.tabValue) {
566
+ setActiveTab(tab.dataset.tabValue);
567
+ updateTabs(tab.dataset.tabValue);
568
+ }
569
+ });
570
+ initializeTabs();
571
+ const observer = new MutationObserver(() => {
572
+ initializeTabs();
573
+ });
574
+ observer.observe(containerRef, {
575
+ childList: true,
576
+ subtree: true
577
+ });
578
+ onCleanup3(() => observer.disconnect());
579
+ });
541
580
  const classes = () => `tabs ${local.class ?? ""}`.trim();
542
- return <TabsContext.Provider value={{ activeTab, setActiveTab }}>
543
- <div class={classes()} {...rest}>
544
- {local.children}
545
- </div>
546
- </TabsContext.Provider>;
581
+ return <div ref={containerRef} class={classes()} data-default-value={local.defaultValue} {...rest}>
582
+ {local.children}
583
+ </div>;
547
584
  }
548
585
  function TabList(props) {
549
586
  const [local, rest] = splitProps15(props, ["children", "class"]);
@@ -554,28 +591,14 @@ function TabList(props) {
554
591
  }
555
592
  function Tab(props) {
556
593
  const [local, rest] = splitProps15(props, ["value", "children", "class"]);
557
- const ctx = useContext4(TabsContext);
558
- const isActive = () => ctx?.activeTab() === local.value;
559
- const handleClick = () => {
560
- ctx?.setActiveTab(local.value);
561
- };
562
- const classes = () => {
563
- const parts = ["tab"];
564
- if (isActive()) {
565
- parts.push("active");
566
- }
567
- if (local.class) {
568
- parts.push(local.class);
569
- }
570
- return parts.join(" ");
571
- };
594
+ const classes = () => `tab ${local.class ?? ""}`.trim();
572
595
  return <button
573
596
  type="button"
574
597
  role="tab"
575
- aria-selected={isActive()}
576
- tabIndex={isActive() ? 0 : -1}
598
+ aria-selected="false"
599
+ tabIndex={-1}
577
600
  class={classes()}
578
- onClick={handleClick}
601
+ data-tab-value={local.value}
579
602
  {...rest}
580
603
  >
581
604
  {local.children}
@@ -583,25 +606,21 @@ function Tab(props) {
583
606
  }
584
607
  function TabPanel(props) {
585
608
  const [local, rest] = splitProps15(props, ["value", "children", "class"]);
586
- const ctx = useContext4(TabsContext);
587
- const isActive = () => ctx?.activeTab() === local.value;
588
609
  const classes = () => `tab-panel ${local.class ?? ""}`.trim();
589
- return <Show6 when={isActive()}>
590
- <div class={classes()} role="tabpanel" {...rest}>
591
- {local.children}
592
- </div>
593
- </Show6>;
610
+ return <div class={classes()} role="tabpanel" data-panel-value={local.value} hidden {...rest}>
611
+ {local.children}
612
+ </div>;
594
613
  }
595
614
 
596
615
  // src/components/Checkbox.tsx
597
- import { splitProps as splitProps16, createEffect, onMount as onMount3 } from "solid-js";
616
+ import { splitProps as splitProps16, createEffect, onMount as onMount4 } from "solid-js";
598
617
  function Checkbox(props) {
599
618
  const [local, rest] = splitProps16(props, ["label", "description", "indeterminate", "class", "disabled", "id"]);
600
619
  let inputRef;
601
620
  const setIndeterminate = () => {
602
621
  if (inputRef) inputRef.indeterminate = local.indeterminate ?? false;
603
622
  };
604
- onMount3(setIndeterminate);
623
+ onMount4(setIndeterminate);
605
624
  createEffect(setIndeterminate);
606
625
  const classes = () => `checkbox ${local.disabled ? "checkbox-disabled" : ""} ${local.class ?? ""}`.trim();
607
626
  const inputId = () => local.id ?? (local.label ? `checkbox-${local.label.toLowerCase().replace(/\s+/g, "-")}` : void 0);
@@ -646,29 +665,29 @@ function Toggle(props) {
646
665
  }
647
666
 
648
667
  // src/components/FormField.tsx
649
- import { splitProps as splitProps18, Show as Show7 } from "solid-js";
668
+ import { splitProps as splitProps18, Show as Show6 } from "solid-js";
650
669
  function FormField(props) {
651
670
  const [local, rest] = splitProps18(props, ["label", "error", "description", "required", "children", "id", "class"]);
652
671
  const classes = () => `form-field ${local.error ? "form-field-has-error" : ""} ${local.class ?? ""}`.trim();
653
672
  return <div class={classes()} {...rest}>
654
673
  <label class="form-field-label" for={local.id}>
655
674
  {local.label}
656
- <Show7 when={local.required}>
675
+ <Show6 when={local.required}>
657
676
  <span class="form-field-required" aria-hidden="true">*</span>
658
- </Show7>
677
+ </Show6>
659
678
  </label>
660
- <Show7 when={local.description}>
679
+ <Show6 when={local.description}>
661
680
  <span class="form-field-description">{local.description}</span>
662
- </Show7>
681
+ </Show6>
663
682
  {local.children}
664
- <Show7 when={local.error}>
683
+ <Show6 when={local.error}>
665
684
  <span class="form-field-error" role="alert">{local.error}</span>
666
- </Show7>
685
+ </Show6>
667
686
  </div>;
668
687
  }
669
688
 
670
689
  // src/components/Timeline.tsx
671
- import { splitProps as splitProps19, For as For3, Show as Show8 } from "solid-js";
690
+ import { splitProps as splitProps19, For as For2, Show as Show7 } from "solid-js";
672
691
  var variantClasses3 = {
673
692
  default: "",
674
693
  success: "timeline-item-success",
@@ -687,27 +706,27 @@ function Timeline(props) {
687
706
  return parts.join(" ");
688
707
  };
689
708
  return <div class={classes()} {...rest}>
690
- <For3 each={local.items}>
709
+ <For2 each={local.items}>
691
710
  {(item, index) => <div
692
711
  class={`timeline-item vertical-connector-item ${variantClasses3[item.variant ?? "default"]}`}
693
712
  >
694
713
  <div class="timeline-indicator vertical-indicator">
695
- <Show8 when={item.icon} fallback={<DefaultDot />}>
714
+ <Show7 when={item.icon} fallback={<DefaultDot />}>
696
715
  {item.icon}
697
- </Show8>
716
+ </Show7>
698
717
  </div>
699
718
  <div class="vertical-connector" />
700
719
  <div class="timeline-content vertical-content">
701
720
  <div class="timeline-title">{item.title}</div>
702
- <Show8 when={item.description}>
721
+ <Show7 when={item.description}>
703
722
  <div class="timeline-description">{item.description}</div>
704
- </Show8>
705
- <Show8 when={item.timestamp}>
723
+ </Show7>
724
+ <Show7 when={item.timestamp}>
706
725
  <div class="timeline-timestamp">{item.timestamp}</div>
707
- </Show8>
726
+ </Show7>
708
727
  </div>
709
728
  </div>}
710
- </For3>
729
+ </For2>
711
730
  </div>;
712
731
  }
713
732
  export {
package/dist/styles.css CHANGED
@@ -1228,6 +1228,10 @@
1228
1228
  color: var(--fg-muted);
1229
1229
  }
1230
1230
 
1231
+ .step-body {
1232
+ margin-top: var(--space-sm);
1233
+ }
1234
+
1231
1235
  /* Tabs */
1232
1236
  .tabs {
1233
1237
  display: flex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@f0rbit/ui",
3
- "version": "0.1.2",
3
+ "version": "0.1.6",
4
4
  "description": "A minimal, composable UI component library for SolidJS",
5
5
  "type": "module",
6
6
  "main": "./dist/server.js",
@@ -46,7 +46,8 @@
46
46
  "./styles/tokens": "./dist/tokens.css",
47
47
  "./styles/reset": "./dist/reset.css",
48
48
  "./styles/utilities": "./dist/utilities.css",
49
- "./styles/components": "./dist/components.css"
49
+ "./styles/components": "./dist/components.css",
50
+ "./styles/starlight": "./docs/src/styles/starlight.css"
50
51
  },
51
52
  "files": ["dist", "src"],
52
53
  "scripts": {
@@ -18,6 +18,11 @@ export interface StepProps extends JSX.HTMLAttributes<HTMLDivElement> {
18
18
  description?: string;
19
19
  icon?: JSX.Element;
20
20
  status?: StepStatus;
21
+ children?: JSX.Element;
22
+ /** Explicit step number (optional, auto-increments if not provided) */
23
+ number?: number;
24
+ /** Explicit orientation (optional, uses context if not provided) */
25
+ orientation?: "horizontal" | "vertical";
21
26
  }
22
27
 
23
28
  const statusClasses: Record<StepStatus, string> = {
@@ -41,12 +46,12 @@ type StepContextValue = {
41
46
  const StepContext = createContext<StepContextValue>();
42
47
 
43
48
  export function Step(props: StepProps) {
44
- const [local, rest] = splitProps(props, ["title", "description", "icon", "status", "class"]);
49
+ const [local, rest] = splitProps(props, ["title", "description", "icon", "status", "class", "children", "number", "orientation"]);
45
50
  const stepperCtx = useContext(StepperContext);
46
51
  const stepCtx = useContext(StepContext);
47
52
 
48
- const stepNumber = stepperCtx?.registerStep() ?? 1;
49
- const orientation = () => stepCtx?.orientation() ?? "horizontal";
53
+ const stepNumber = local.number ?? stepperCtx?.registerStep() ?? 1;
54
+ const orientation = () => local.orientation ?? stepCtx?.orientation() ?? "vertical";
50
55
 
51
56
  const status = () => local.status ?? "upcoming";
52
57
 
@@ -105,6 +110,9 @@ export function Step(props: StepProps) {
105
110
  <Show when={local.description}>
106
111
  <div class="step-description">{local.description}</div>
107
112
  </Show>
113
+ <Show when={local.children}>
114
+ <div class="step-body">{local.children}</div>
115
+ </Show>
108
116
  </div>
109
117
  <div class={connectorClasses()} />
110
118
  </div>