starting-point-ui 0.0.1

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/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # Starting Point UI
2
+
3
+ A component library built on top of Tailwind CSS. Framework agnostic, easy to customize, open source, and works in any project. Inspired by [shadcn/ui](https://ui.shadcn.com).
4
+
5
+ ## Getting Started
6
+
7
+ Visit [startingpointui.com/docs/guides/installation](https://www.startingpointui.com/docs/guides/installation) to get started.
8
+
9
+ ## Documentation
10
+
11
+ Visit [startingpointui.com](https://www.startingpointui.com) for full documentation, component examples, and guides.
12
+
13
+ ## Community
14
+
15
+ - [GitHub Discussions](https://github.com/gufodotdev/starting-point-ui/discussions) - Ask questions or suggest features
16
+ - [GitHub Issues](https://github.com/gufodotdev/starting-point-ui/issues) - Report bugs
17
+
18
+ ## License
19
+
20
+ MIT
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ @layer components{.btn{@apply inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*="size-"])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive;@apply [&:where(&:not(.btn-default,.btn-destructive,.btn-outline,.btn-secondary,.btn-ghost,.btn-link))]:btn-default;@apply [&:where(&:not(.btn-base,.btn-sm,.btn-lg,.btn-icon,.btn-icon-sm,.btn-icon-lg))]:btn-base;}}@utility btn-default{@apply bg-primary text-primary-foreground hover:bg-primary/90;}@utility btn-destructive{@apply bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60;}@utility btn-outline{@apply border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50;}@utility btn-secondary{@apply bg-secondary text-secondary-foreground hover:bg-secondary/80;}@utility btn-ghost{@apply hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50;}@utility btn-link{@apply text-primary underline-offset-4 hover:underline;}@utility btn-sm{@apply h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5;}@utility btn-base{@apply h-9 px-4 py-2 has-[>svg]:px-3;}@utility btn-lg{@apply h-10 rounded-md px-6 has-[>svg]:px-4;}@utility btn-icon-sm{@apply size-8;}@utility btn-icon{@apply size-9;}@utility btn-icon-lg{@apply size-10;}@layer components{.card{@apply text-card-foreground rounded-xl;@apply [&:where(&:not(.card-default,.card-outline,.card-muted))]:card-default;}.card-content{@apply [&:where(&:not(.card-content-sm,.card-content-base,.card-content-lg))]:card-content-base;}}@utility card-default{@apply bg-card border shadow-sm;}@utility card-outline{@apply bg-card border;}@utility card-muted{@apply bg-muted;}@utility card-content-sm{@apply p-4;}@utility card-content-base{@apply p-6;}@utility card-content-lg{@apply p-12;}@layer components{.checkbox{@apply border-input size-4 shrink-0 rounded-[4px] border shadow-xs transition-[box-shadow,background-color,border-color] outline-none appearance-none cursor-pointer;@apply dark:bg-input/30;@apply checked:bg-primary checked:border-primary;@apply disabled:cursor-not-allowed disabled:opacity-50;@apply focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px];@apply aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive;}.checkbox:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");background-size:100% 100%;background-position:center;background-repeat:no-repeat}.dark .checkbox:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='black' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}}@utility container{@apply px-6 w-full max-w-3xl lg:max-w-7xl mx-auto;}@utility container-wide{@apply px-6 w-full max-w-7xl mx-auto;}@utility container-fluid{@apply px-6 w-full;}@layer components{.dialog{@apply isolate pointer-events-none fixed inset-0 z-999 w-full h-dvh p-0 bg-transparent border-none max-w-none max-h-none overflow-hidden;}.dialog::backdrop{@apply hidden;}.dialog-backdrop{@apply fixed inset-0 bg-black/50 -z-1 pointer-events-auto fill-mode-forwards!;}.dialog-panel{@apply fixed pointer-events-auto top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-background rounded-lg shadow-lg p-6 max-w-md w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] overflow-y-auto fill-mode-forwards!;}}@layer components{.input{@apply border-input w-full min-w-0 rounded-md border bg-transparent px-3 text-sm shadow-xs transition-[color,box-shadow] outline-none;@apply placeholder:text-muted-foreground;@apply dark:bg-input/30;@apply file:text-foreground file:inline-flex file:border-0 file:bg-transparent file:text-sm file:font-medium;@apply selection:bg-primary selection:text-primary-foreground;@apply disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50;@apply focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px];@apply aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive;@apply [&:where(&:not(.input-sm,.input-base,.input-lg))]:input-base;}}@utility input-sm{@apply h-8 file:h-8;}@utility input-base{@apply h-9 file:h-9;}@utility input-lg{@apply h-10 file:h-10;}@layer components{.label{@apply flex items-center gap-2 text-sm leading-none font-medium select-none;@apply group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50;@apply peer-disabled:cursor-not-allowed peer-disabled:opacity-50;}}@layer components{.select{@apply border-input w-full min-w-0 appearance-none rounded-md border bg-transparent text-sm shadow-xs transition-[color,box-shadow] outline-none;@apply placeholder:text-muted-foreground;@apply selection:bg-primary selection:text-primary-foreground;@apply dark:bg-input/30 dark:hover:bg-input/50;@apply disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50;@apply focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px];@apply aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive;@apply [&:where(&:not(.select-sm,.select-base,.select-lg))]:select-base;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m6 9 6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:1rem}}@utility select-sm{@apply h-8 px-3 pr-9;}@utility select-base{@apply h-9 px-3 pr-9;}@utility select-lg{@apply h-10 px-3 pr-9;}@layer components{.tab-list{@apply bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px];}.tab{@apply text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*="size-"])]:size-4;@apply outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] focus-visible:outline-1 focus-visible:outline-ring;}.tab.active{@apply bg-background shadow-sm dark:text-foreground dark:border-input dark:bg-input/30;}.tab-panel{@apply hidden w-full min-w-0 outline-none;}.tab-panel.active{@apply block;}}@layer components{.textarea{@apply border-input w-full rounded-md border bg-transparent shadow-xs transition-[color,box-shadow] outline-none;@apply placeholder:text-muted-foreground;@apply dark:bg-input/30;@apply field-sizing-content min-h-16 px-3 py-2 text-sm;@apply disabled:cursor-not-allowed disabled:opacity-50;@apply focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px];@apply aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive;}}@custom-variant dark (&:is(.dark *));:root{--radius: .625rem;--background: oklch(1 0 0);--foreground: oklch(.145 0 0);--card: oklch(1 0 0);--card-foreground: oklch(.145 0 0);--popover: oklch(1 0 0);--popover-foreground: oklch(.145 0 0);--primary: oklch(.205 0 0);--primary-foreground: oklch(.985 0 0);--secondary: oklch(.97 0 0);--secondary-foreground: oklch(.205 0 0);--muted: oklch(.97 0 0);--muted-foreground: oklch(.556 0 0);--accent: oklch(.97 0 0);--accent-foreground: oklch(.205 0 0);--destructive: oklch(.577 .245 27.325);--border: oklch(.922 0 0);--input: oklch(.922 0 0);--ring: oklch(.708 0 0)}.dark{--background: oklch(.145 0 0);--foreground: oklch(.985 0 0);--card: oklch(.205 0 0);--card-foreground: oklch(.985 0 0);--popover: oklch(.205 0 0);--popover-foreground: oklch(.985 0 0);--primary: oklch(.922 0 0);--primary-foreground: oklch(.205 0 0);--secondary: oklch(.269 0 0);--secondary-foreground: oklch(.985 0 0);--muted: oklch(.269 0 0);--muted-foreground: oklch(.708 0 0);--accent: oklch(.269 0 0);--accent-foreground: oklch(.985 0 0);--destructive: oklch(.704 .191 22.216);--border: oklch(1 0 0 / 10%);--input: oklch(1 0 0 / 15%);--ring: oklch(.556 0 0)}@theme inline{ --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); }@layer base{*{@apply border-border outline-ring/50;}html{scrollbar-gutter:stable}html:has(dialog[open] .dialog-backdrop){@apply overflow-hidden;}body,.dark{@apply bg-background text-foreground;}}
@@ -0,0 +1,28 @@
1
+ declare function open(dialog: HTMLDialogElement): void;
2
+ declare function close(dialog: HTMLDialogElement): Promise<void>;
3
+ declare function toggle(dialog: HTMLDialogElement): void;
4
+
5
+ declare const dialog_close: typeof close;
6
+ declare const dialog_open: typeof open;
7
+ declare const dialog_toggle: typeof toggle;
8
+ declare namespace dialog {
9
+ export { dialog_close as close, dialog_open as open, dialog_toggle as toggle };
10
+ }
11
+
12
+ declare function select(tab: HTMLElement): void;
13
+
14
+ declare const tabs_select: typeof select;
15
+ declare namespace tabs {
16
+ export { tabs_select as select };
17
+ }
18
+
19
+ declare global {
20
+ interface Window {
21
+ sp: {
22
+ dialog: typeof dialog;
23
+ tabs: typeof tabs;
24
+ };
25
+ }
26
+ }
27
+
28
+ export { dialog, tabs };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ var M=Object.defineProperty;var b=(e,t)=>{for(var n in t)M(e,n,{get:t[n],enumerable:true});};var u={};b(u,{close:()=>a,open:()=>d,toggle:()=>v});var H=["a[href]","button:not([disabled])","input:not([disabled])","select:not([disabled])","textarea:not([disabled])","[tabindex]:not([tabindex='-1'])","[contenteditable]:not([contenteditable='false'])","audio[controls]","video[controls]","details > summary","iframe"].join(", ");function c(e){return [...e.querySelectorAll(H)].filter(t=>t.offsetParent!==null)}function g(e){return [...e.querySelectorAll(".dialog-backdrop, .dialog-panel")]}function r(e,t){for(let n of e)t===null?n.removeAttribute("data-state"):n.setAttribute("data-state",t);}async function y(e){let t=e.flatMap(n=>n.getAnimations());t.length!==0&&await Promise.all(t.map(n=>n.finished));}function p(e){return e.querySelector(".dialog-backdrop")!==null}function d(e){e.show();let t=g(e);if(r(t,"open"),p(e)){let n=c(e);n.length>0&&n[0].focus();}}async function a(e){let t=g(e);r(t,"closed"),await y(t),e.close(),r(t,null);}function v(e){e.open?a(e):d(e);}function h(e){let t=e.target.closest("dialog");if(t?.open){if(e.key==="Escape"){e.preventDefault(),t.dataset.spBackdrop==="static"||a(t);return}if(e.key==="Tab"&&p(t)){let n=c(t);if(n.length===0)return;let l=n[0],s=n[n.length-1];e.shiftKey&&document.activeElement===l?(e.preventDefault(),s.focus()):!e.shiftKey&&document.activeElement===s&&(e.preventDefault(),l.focus());}}}function A(e){let t=e.target,n=t.closest("[data-sp-toggle='dialog']");if(n){let o=n.dataset.spTarget;if(o){let i=document.querySelector(o);i&&d(i);}return}let l=t.closest("[data-sp-dismiss='dialog']");if(l){let o=l.closest("dialog");o&&a(o);return}let s=t.closest(".dialog-backdrop");if(s){let o=s.closest("dialog");o&&(o.dataset.spBackdrop==="static"||a(o));}}var E=false;(function(){typeof document>"u"||E||(E=true,document.addEventListener("click",A),document.addEventListener("keydown",h));})();var m={};b(m,{select:()=>f});function f(e){if(e.hasAttribute("disabled"))return;let t=e.closest(".tab-list");if(!t)return;let n=t.querySelectorAll(".tab");for(let s of n){s.classList.remove("active"),s.setAttribute("aria-selected","false"),s.setAttribute("tabindex","-1");let o=s.dataset.spTarget;o&&document.querySelector(o)?.classList.remove("active");}e.classList.add("active"),e.setAttribute("aria-selected","true"),e.setAttribute("tabindex","0");let l=e.dataset.spTarget;l&&document.querySelector(l)?.classList.add("active");}function k(e){let n=e.target.closest("[data-sp-toggle='tab']");n&&f(n);}function L(e,t,n){let l=e.length;for(let s=1;s<=l;s++){let o=(t+s*n+l)%l;if(!e[o].hasAttribute("disabled"))return e[o]}return null}function w(e){let t=e.target;if(!t.classList.contains("tab"))return;let n=t.closest(".tab-list");if(!n)return;let l=[...n.querySelectorAll(".tab")],s=l.indexOf(t),o=null;switch(e.key){case "ArrowLeft":o=L(l,s,-1);break;case "ArrowRight":o=L(l,s,1);break;case "Home":o=l.find(i=>!i.hasAttribute("disabled"))??null;break;case "End":o=[...l].reverse().find(i=>!i.hasAttribute("disabled"))??null;break}o&&(e.preventDefault(),o.focus(),f(o));}var T=false;(function(){typeof document>"u"||T||(T=true,document.addEventListener("click",k),document.addEventListener("keydown",w));})();typeof window<"u"&&(window.sp={dialog:u,tabs:m});export{u as dialog,m as tabs};//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/js/dialog.ts","../src/js/utils.ts","../src/js/tabs.ts","../src/js/index.ts"],"names":["dialog_exports","__export","close","open","toggle","FOCUSABLE_SELECTOR","getFocusableElements","container","el","getAnimatableElements","dialog","setDataState","elements","state","waitForAnimations","animations","a","isModal","focusable","handleKeydown","dialogEl","first","last","handleClick","target","toggleBtn","selector","dismissBtn","backdrop","initialized","tabs_exports","select","tab","tabList","tabs","t","findNextEnabledTab","startIndex","direction","len","i","index","currentIndex","nextTab"],"mappings":"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","file":"index.js","sourcesContent":["// Starting Point UI Dialog Module\n\nimport { getFocusableElements } from \"./utils\";\n\nfunction getAnimatableElements(dialog: HTMLDialogElement): HTMLElement[] {\n return [\n ...dialog.querySelectorAll<HTMLElement>(\".dialog-backdrop, .dialog-panel\"),\n ];\n}\n\nfunction setDataState(\n elements: HTMLElement[],\n state: \"open\" | \"closed\" | null\n) {\n for (const el of elements) {\n if (state === null) {\n el.removeAttribute(\"data-state\");\n } else {\n el.setAttribute(\"data-state\", state);\n }\n }\n}\n\nasync function waitForAnimations(elements: HTMLElement[]): Promise<void> {\n const animations = elements.flatMap((el) => el.getAnimations());\n if (animations.length === 0) return;\n await Promise.all(animations.map((a) => a.finished));\n}\n\nfunction isModal(dialog: HTMLDialogElement): boolean {\n return dialog.querySelector(\".dialog-backdrop\") !== null;\n}\n\nexport function open(dialog: HTMLDialogElement) {\n dialog.show();\n const elements = getAnimatableElements(dialog);\n setDataState(elements, \"open\");\n\n // Focus first focusable element in modal dialogs\n if (isModal(dialog)) {\n const focusable = getFocusableElements(dialog);\n if (focusable.length > 0) {\n focusable[0].focus();\n }\n }\n}\n\nexport async function close(dialog: HTMLDialogElement) {\n const elements = getAnimatableElements(dialog);\n setDataState(elements, \"closed\");\n\n await waitForAnimations(elements);\n\n dialog.close();\n setDataState(elements, null);\n}\n\nexport function toggle(dialog: HTMLDialogElement) {\n if (dialog.open) {\n close(dialog);\n } else {\n open(dialog);\n }\n}\n\n// Handle keydown for Escape and focus trapping\nfunction handleKeydown(e: KeyboardEvent) {\n const dialogEl = (e.target as HTMLElement).closest<HTMLDialogElement>(\n \"dialog\"\n );\n if (!dialogEl?.open) return;\n\n // Handle Escape key\n if (e.key === \"Escape\") {\n e.preventDefault();\n const isStatic = dialogEl.dataset.spBackdrop === \"static\";\n if (!isStatic) {\n close(dialogEl);\n }\n return;\n }\n\n // Handle Tab key for focus trapping in modals\n if (e.key === \"Tab\" && isModal(dialogEl)) {\n const focusable = getFocusableElements(dialogEl);\n if (focusable.length === 0) return;\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n}\n\n// Global click handler for data attributes\nfunction handleClick(e: MouseEvent) {\n const target = e.target as HTMLElement;\n\n // Handle toggle buttons\n const toggleBtn = target.closest<HTMLElement>(\"[data-sp-toggle='dialog']\");\n if (toggleBtn) {\n const selector = toggleBtn.dataset.spTarget;\n if (selector) {\n const dialogEl = document.querySelector<HTMLDialogElement>(selector);\n if (dialogEl) {\n open(dialogEl);\n }\n }\n return;\n }\n\n // Handle dismiss buttons\n const dismissBtn = target.closest<HTMLElement>(\"[data-sp-dismiss='dialog']\");\n if (dismissBtn) {\n const dialogEl = dismissBtn.closest<HTMLDialogElement>(\"dialog\");\n if (dialogEl) {\n close(dialogEl);\n }\n return;\n }\n\n // Handle backdrop clicks\n const backdrop = target.closest<HTMLElement>(\".dialog-backdrop\");\n if (backdrop) {\n const dialogEl = backdrop.closest<HTMLDialogElement>(\"dialog\");\n if (dialogEl) {\n // Static backdrop prevents closing via click\n const isStatic = dialogEl.dataset.spBackdrop === \"static\";\n if (!isStatic) {\n close(dialogEl);\n }\n }\n }\n}\n\n// Initialize global listeners\nlet initialized = false;\n\n(function init() {\n if (typeof document === \"undefined\" || initialized) return;\n initialized = true;\n\n document.addEventListener(\"click\", handleClick);\n document.addEventListener(\"keydown\", handleKeydown);\n})();\n","// Starting Point UI Utilities\n\nconst FOCUSABLE_SELECTOR = [\n \"a[href]\",\n \"button:not([disabled])\",\n \"input:not([disabled])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n \"[tabindex]:not([tabindex='-1'])\",\n \"[contenteditable]:not([contenteditable='false'])\",\n \"audio[controls]\",\n \"video[controls]\",\n \"details > summary\",\n \"iframe\",\n].join(\", \");\n\nexport function getFocusableElements(container: HTMLElement): HTMLElement[] {\n return [...container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)].filter(\n (el) => el.offsetParent !== null\n );\n}\n","// Starting Point UI Tabs Module\n\nexport function select(tab: HTMLElement) {\n if (tab.hasAttribute(\"disabled\")) return;\n\n const tabList = tab.closest(\".tab-list\");\n if (!tabList) return;\n\n // Deselect all tabs in the list\n const tabs = tabList.querySelectorAll<HTMLElement>(\".tab\");\n for (const t of tabs) {\n t.classList.remove(\"active\");\n t.setAttribute(\"aria-selected\", \"false\");\n t.setAttribute(\"tabindex\", \"-1\");\n const selector = t.dataset.spTarget;\n if (selector) {\n document.querySelector(selector)?.classList.remove(\"active\");\n }\n }\n\n // Select the clicked tab\n tab.classList.add(\"active\");\n tab.setAttribute(\"aria-selected\", \"true\");\n tab.setAttribute(\"tabindex\", \"0\");\n\n const selector = tab.dataset.spTarget;\n if (selector) {\n document.querySelector(selector)?.classList.add(\"active\");\n }\n}\n\nfunction handleClick(e: MouseEvent) {\n const target = e.target as HTMLElement;\n const tab = target.closest<HTMLElement>(\"[data-sp-toggle='tab']\");\n if (tab) {\n select(tab);\n }\n}\n\nfunction findNextEnabledTab(\n tabs: HTMLElement[],\n startIndex: number,\n direction: 1 | -1\n): HTMLElement | null {\n const len = tabs.length;\n for (let i = 1; i <= len; i++) {\n const index = (startIndex + i * direction + len) % len;\n if (!tabs[index].hasAttribute(\"disabled\")) {\n return tabs[index];\n }\n }\n return null;\n}\n\nfunction handleKeydown(e: KeyboardEvent) {\n const target = e.target as HTMLElement;\n if (!target.classList.contains(\"tab\")) return;\n\n const tabList = target.closest(\".tab-list\");\n if (!tabList) return;\n\n const tabs = [...tabList.querySelectorAll<HTMLElement>(\".tab\")];\n const currentIndex = tabs.indexOf(target);\n\n let nextTab: HTMLElement | null = null;\n\n switch (e.key) {\n case \"ArrowLeft\":\n nextTab = findNextEnabledTab(tabs, currentIndex, -1);\n break;\n case \"ArrowRight\":\n nextTab = findNextEnabledTab(tabs, currentIndex, 1);\n break;\n case \"Home\":\n nextTab = tabs.find((t) => !t.hasAttribute(\"disabled\")) ?? null;\n break;\n case \"End\":\n nextTab = [...tabs].reverse().find((t) => !t.hasAttribute(\"disabled\")) ?? null;\n break;\n }\n\n if (nextTab) {\n e.preventDefault();\n nextTab.focus();\n select(nextTab);\n }\n}\n\n// Initialize global listeners\nlet initialized = false;\n\n(function init() {\n if (typeof document === \"undefined\" || initialized) return;\n initialized = true;\n\n document.addEventListener(\"click\", handleClick);\n document.addEventListener(\"keydown\", handleKeydown);\n})();\n","// Starting Point UI - JavaScript\n\nimport * as dialog from \"./dialog\";\nimport * as tabs from \"./tabs\";\n\nexport { dialog, tabs };\n\ndeclare global {\n interface Window {\n sp: { dialog: typeof dialog; tabs: typeof tabs };\n }\n}\n\nif (typeof window !== \"undefined\") {\n window.sp = { dialog, tabs };\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "starting-point-ui",
3
+ "version": "0.0.1",
4
+ "description": "A component library built on top of Tailwind CSS. Framework agnostic, easy to customize, open source, and works in any project.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "style": "./dist/index.css",
9
+ "exports": {
10
+ ".": {
11
+ "style": "./dist/index.css",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.css"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "dev": "tsup --watch",
22
+ "check-types": "tsc --noEmit",
23
+ "lint": "eslint src/"
24
+ },
25
+ "devDependencies": {
26
+ "@eslint/js": "^9",
27
+ "eslint": "^9",
28
+ "tsup": "^8.3.5",
29
+ "typescript": "^5.7.3",
30
+ "typescript-eslint": "^8"
31
+ },
32
+ "keywords": [
33
+ "tailwindcss",
34
+ "components",
35
+ "shadcn",
36
+ "ui"
37
+ ],
38
+ "license": "MIT",
39
+ "author": "Gufo",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/gufodotdev/starting-point-ui.git",
43
+ "directory": "packages/ui"
44
+ },
45
+ "homepage": "https://www.startingpointui.com",
46
+ "bugs": {
47
+ "url": "https://github.com/gufodotdev/starting-point-ui/issues"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ }
52
+ }