@inshorts/glint-ui 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/autocomplete.cjs.map +1 -1
  2. package/dist/autocomplete.js +2 -2
  3. package/dist/{chunk-PVK4WQJZ.js → chunk-5MEOZHJA.js} +2 -2
  4. package/dist/{chunk-43ZUFY63.js → chunk-A6GRLKOO.js} +3 -3
  5. package/dist/chunk-A6GRLKOO.js.map +1 -0
  6. package/dist/{chunk-YSU4VWRD.js → chunk-DS3QYIKL.js} +2 -2
  7. package/dist/{chunk-YSU4VWRD.js.map → chunk-DS3QYIKL.js.map} +1 -1
  8. package/dist/{chunk-WVNRFO5F.js → chunk-ISPICB4W.js} +2 -2
  9. package/dist/{chunk-ASU6CUTZ.js → chunk-MLRSOTFI.js} +5 -9
  10. package/dist/chunk-MLRSOTFI.js.map +1 -0
  11. package/dist/{chunk-6URKHMCF.js → chunk-OUYT6SPU.js} +2 -2
  12. package/dist/confirm-dialog.cjs +1 -1
  13. package/dist/confirm-dialog.cjs.map +1 -1
  14. package/dist/confirm-dialog.js +2 -2
  15. package/dist/index.cjs +6 -10
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.js +6 -6
  18. package/dist/modal.cjs +1 -1
  19. package/dist/modal.cjs.map +1 -1
  20. package/dist/modal.js +1 -1
  21. package/dist/segmented-control.cjs +4 -8
  22. package/dist/segmented-control.cjs.map +1 -1
  23. package/dist/segmented-control.d.cts +5 -7
  24. package/dist/segmented-control.d.ts +5 -7
  25. package/dist/segmented-control.js +1 -1
  26. package/dist/select.cjs.map +1 -1
  27. package/dist/select.js +3 -3
  28. package/dist/side-drawer.cjs +1 -1
  29. package/dist/side-drawer.cjs.map +1 -1
  30. package/dist/side-drawer.js +2 -2
  31. package/package.json +9 -8
  32. package/LICENSE +0 -13
  33. package/dist/chunk-43ZUFY63.js.map +0 -1
  34. package/dist/chunk-ASU6CUTZ.js.map +0 -1
  35. /package/dist/{chunk-PVK4WQJZ.js.map → chunk-5MEOZHJA.js.map} +0 -0
  36. /package/dist/{chunk-WVNRFO5F.js.map → chunk-ISPICB4W.js.map} +0 -0
  37. /package/dist/{chunk-6URKHMCF.js.map → chunk-OUYT6SPU.js.map} +0 -0
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  SideDrawer
4
- } from "./chunk-43ZUFY63.js";
5
- import "./chunk-YSU4VWRD.js";
4
+ } from "./chunk-A6GRLKOO.js";
5
+ import "./chunk-DS3QYIKL.js";
6
6
  import "./chunk-HBBOR43A.js";
7
7
  import "./chunk-KR3BCFP7.js";
8
8
  import "./chunk-UE7JY7VR.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inshorts/glint-ui",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Glint Tailwind 4 UI kit for Inshorts Next panels.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -408,6 +408,12 @@
408
408
  "url": "git+https://github.com/NewsInShorts/inshorts-npm-modules.git",
409
409
  "directory": "glint/ui"
410
410
  },
411
+ "scripts": {
412
+ "build": "tsup && node scripts/write-exports.mjs",
413
+ "typecheck": "tsc --noEmit",
414
+ "test": "vitest run",
415
+ "prepublishOnly": "npm run typecheck && npm test && npm run build"
416
+ },
411
417
  "peerDependencies": {
412
418
  "@radix-ui/react-slot": "^1.2.0",
413
419
  "lucide-react": "^0.400.0 || ^1.0.0",
@@ -420,7 +426,7 @@
420
426
  }
421
427
  },
422
428
  "dependencies": {
423
- "@inshorts/glint-theme": "^0.5.1",
429
+ "@inshorts/glint-theme": "^0.6.1",
424
430
  "class-variance-authority": "^0.7.1",
425
431
  "clsx": "^2.1.1",
426
432
  "tailwind-merge": "^3.7.0"
@@ -445,10 +451,5 @@
445
451
  },
446
452
  "publishConfig": {
447
453
  "access": "public"
448
- },
449
- "scripts": {
450
- "build": "tsup && node scripts/write-exports.mjs",
451
- "typecheck": "tsc --noEmit",
452
- "test": "vitest run"
453
454
  }
454
- }
455
+ }
package/LICENSE DELETED
@@ -1,13 +0,0 @@
1
- UNLICENSED
2
-
3
- Copyright (c) Inshorts / News In Shorts Private Limited.
4
-
5
- These packages are published to the public npm registry under the `@inshorts`
6
- scope for install convenience (Docker / CI without a private registry). They
7
- are NOT open source.
8
-
9
- You may use them only as part of Inshorts internal products and services.
10
- Redistribution, sublicensing, or use outside Inshorts requires written
11
- permission from News In Shorts Private Limited.
12
-
13
- All rights reserved.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/side-drawer.tsx"],"sourcesContent":["\"use client\";\n\nimport { X } from \"lucide-react\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { Button } from \"./button\";\nimport { useDialogLayer } from \"./dialogLayer\";\nimport { useHasMounted } from \"./modal\";\nimport { cn } from \"./utils\";\n\ninterface SideDrawerProps {\n isOpen: boolean;\n title: string;\n onClose: () => void;\n children: React.ReactNode;\n /** Tailwind width class for the panel. Defaults to a reading-width column. */\n panelClassName?: string;\n}\n\n/**\n * A panel that slides in from the right.\n *\n * For content that belongs beside the page rather than on top of it — a queue\n * you glance at and dismiss, not a decision you have to answer. Unlike\n * `Modal`, it does not centre or dim the whole page to a stop: the table\n * underneath stays readable, which is the point of looking at both.\n */\nexport function SideDrawer({\n isOpen,\n title,\n onClose,\n children,\n panelClassName,\n}: SideDrawerProps) {\n const mounted = useHasMounted();\n const headingId = React.useId();\n const panelRef = React.useRef<HTMLElement>(null);\n\n useDialogLayer({\n // Gated on `mounted` too: before that the panel is not rendered, so there\n // would be nothing to move focus into.\n active: isOpen && mounted,\n containerRef: panelRef,\n onEscape: onClose,\n });\n\n if (!mounted || !isOpen) return null;\n\n return createPortal(\n <>\n <div\n aria-hidden\n onClick={onClose}\n className=\"fixed inset-0 z-[90] bg-slate-950/30\"\n />\n <aside\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={headingId}\n tabIndex={-1}\n className={cn(\n \"border-border bg-background fixed inset-y-0 right-0 z-[95] flex flex-col border-l shadow-2xl outline-none\",\n panelClassName ?? \"w-full max-w-md\",\n )}\n >\n <div className=\"border-border flex items-center justify-between gap-3 border-b px-4 py-3\">\n <h2 id={headingId} className=\"truncate text-base font-semibold\">\n {title}\n </h2>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"Close panel\"\n onClick={onClose}\n >\n <X className=\"h-4 w-4\" aria-hidden />\n </Button>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto p-4\">{children}</div>\n </aside>\n </>,\n document.body,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAEA,SAAS,SAAS;AAClB,YAAY,WAAW;AACvB,SAAS,oBAAoB;AA8CzB,mBACE,KAgBE,YAjBJ;AAtBG,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,UAAU,cAAc;AAC9B,QAAM,YAAkB,YAAM;AAC9B,QAAM,WAAiB,aAAoB,IAAI;AAE/C,iBAAe;AAAA;AAAA;AAAA,IAGb,QAAQ,UAAU;AAAA,IAClB,cAAc;AAAA,IACd,UAAU;AAAA,EACZ,CAAC;AAED,MAAI,CAAC,WAAW,CAAC,OAAQ,QAAO;AAEhC,SAAO;AAAA,IACL,iCACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,UACX,SAAS;AAAA,UACT,WAAU;AAAA;AAAA,MACZ;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,cAAW;AAAA,UACX,mBAAiB;AAAA,UACjB,UAAU;AAAA,UACV,WAAW;AAAA,YACT;AAAA,YACA,kBAAkB;AAAA,UACpB;AAAA,UAEA;AAAA,iCAAC,SAAI,WAAU,4EACb;AAAA,kCAAC,QAAG,IAAI,WAAW,WAAU,oCAC1B,iBACH;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,cAAW;AAAA,kBACX,SAAS;AAAA,kBAET,8BAAC,KAAE,WAAU,WAAU,eAAW,MAAC;AAAA;AAAA,cACrC;AAAA,eACF;AAAA,YAEA,oBAAC,SAAI,WAAU,sCAAsC,UAAS;AAAA;AAAA;AAAA,MAChE;AAAA,OACF;AAAA,IACA,SAAS;AAAA,EACX;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/segmented-control.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The one-of-N picker seven panels were each drawing by hand.\n *\n * Not `Tabs`, which is a bottom-bordered strip sitting above the content it\n * switches. This is the inline version — a bordered track with the selected\n * option filled in — used for a filter or a setting that sits among other\n * controls rather than heading a panel.\n *\n * **Roles are the reason to use this.** The seven copies had three different\n * ideas about what they were: one said `tablist`/`tab`, one said\n * `group`/`aria-pressed`, and the other five said nothing at all — so on five\n * of seven a screen reader heard a row of unlabelled buttons with no\n * indication which one was active. None of the three was right. `tablist`\n * without a `tabpanel` is a promise the markup does not keep, and\n * `aria-pressed` describes independent toggles, not a choice of one. Picking a\n * value out of a fixed set is a radio group, so that is what this is, with the\n * roving tabindex and arrow keys that come with the role.\n *\n * `tone` keeps both active colours the panels had drifted into: `emphasis` is\n * the near-black/near-white fill five of them used, `primary` the violet\n * accent the other two did. They are genuinely different colours rather than\n * one spelled two ways, so collapsing them is a visual change to two panels\n * and belongs in its own reviewable diff — the same call `DataTable` makes\n * about its two header variants.\n */\nexport interface SegmentedOption<Value extends string> {\n value: Value;\n label: React.ReactNode;\n disabled?: boolean;\n /**\n * Hover text. Worth setting on a disabled option — \"Everyone\" going grey\n * says nothing about which permission would bring it back.\n */\n title?: string;\n}\n\nexport interface SegmentedControlProps<Value extends string> {\n options: ReadonlyArray<SegmentedOption<Value>>;\n value: Value;\n onChange: (value: Value) => void;\n /**\n * Required: the group never has a visible label — the options name the\n * choice between them, which tells you nothing about what is being chosen.\n */\n ariaLabel: string;\n /**\n * `contained` — one bordered track around the options (five panels).\n * `loose` — free-standing pills with a gap between them (two panels).\n */\n variant?: \"contained\" | \"loose\";\n /** See the note above: two real colours, not one spelled twice. */\n tone?: \"emphasis\" | \"primary\";\n /** Options share the width equally, for a control that fills its column. */\n fill?: boolean;\n className?: string;\n}\n\nconst TONES = {\n emphasis: {\n on: \"bg-slate-950 text-white dark:bg-white dark:text-slate-950\",\n off: \"text-muted-foreground hover:bg-muted\",\n },\n primary: {\n on: \"bg-primary text-primary-foreground\",\n off: \"text-muted-foreground hover:bg-muted\",\n },\n} as const;\n\nconst TRACKS = {\n contained: \"border-border inline-flex rounded-md border p-0.5\",\n loose: \"flex flex-wrap gap-2\",\n} as const;\n\nexport function SegmentedControl<Value extends string>({\n options,\n value,\n onChange,\n ariaLabel,\n variant = \"contained\",\n tone = \"emphasis\",\n fill = false,\n className,\n}: SegmentedControlProps<Value>) {\n const refs = React.useRef(new Map<Value, HTMLButtonElement | null>());\n\n function onKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const step =\n event.key === \"ArrowRight\" || event.key === \"ArrowDown\"\n ? 1\n : event.key === \"ArrowLeft\" || event.key === \"ArrowUp\"\n ? -1\n : 0;\n if (step === 0) return;\n\n const selectable = options.filter((option) => !option.disabled);\n if (selectable.length < 2) return;\n\n const current = selectable.findIndex((option) => option.value === value);\n // Wraps, which is what a radio group is expected to do.\n const next =\n selectable[(current + step + selectable.length) % selectable.length];\n\n event.preventDefault();\n onChange(next.value);\n // The newly checked option has to take focus, or the next arrow press is\n // still measured from the old one.\n refs.current.get(next.value)?.focus();\n }\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n onKeyDown={onKeyDown}\n className={cn(TRACKS[variant], className)}\n >\n {options.map((option) => {\n const checked = option.value === value;\n return (\n <button\n key={option.value}\n ref={(node) => {\n refs.current.set(option.value, node);\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n disabled={option.disabled}\n title={option.title}\n // Only the checked option is reachable by Tab; arrows move within\n // the group. Without this a keyboard user pages through every\n // option to get past the control.\n tabIndex={checked ? 0 : -1}\n onClick={() => onChange(option.value)}\n className={cn(\n \"cursor-pointer rounded px-3 py-1 text-sm font-medium transition\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n fill && \"flex-1\",\n checked ? TONES[tone].on : TONES[tone].off,\n )}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;AAEA,YAAY,WAAW;AA2Hb;AA9DV,IAAM,QAAQ;AAAA,EACZ,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AACF;AAEA,IAAM,SAAS;AAAA,EACb,WAAW;AAAA,EACX,OAAO;AACT;AAEO,SAAS,iBAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP;AACF,GAAiC;AAC/B,QAAM,OAAa,aAAO,oBAAI,IAAqC,CAAC;AAEpE,WAAS,UAAU,OAA4C;AAC7D,UAAM,OACJ,MAAM,QAAQ,gBAAgB,MAAM,QAAQ,cACxC,IACA,MAAM,QAAQ,eAAe,MAAM,QAAQ,YACzC,KACA;AACR,QAAI,SAAS,EAAG;AAEhB,UAAM,aAAa,QAAQ,OAAO,CAAC,WAAW,CAAC,OAAO,QAAQ;AAC9D,QAAI,WAAW,SAAS,EAAG;AAE3B,UAAM,UAAU,WAAW,UAAU,CAAC,WAAW,OAAO,UAAU,KAAK;AAEvE,UAAM,OACJ,YAAY,UAAU,OAAO,WAAW,UAAU,WAAW,MAAM;AAErE,UAAM,eAAe;AACrB,aAAS,KAAK,KAAK;AAGnB,SAAK,QAAQ,IAAI,KAAK,KAAK,GAAG,MAAM;AAAA,EACtC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ;AAAA,MACA,WAAW,GAAG,OAAO,OAAO,GAAG,SAAS;AAAA,MAEvC,kBAAQ,IAAI,CAAC,WAAW;AACvB,cAAM,UAAU,OAAO,UAAU;AACjC,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,KAAK,CAAC,SAAS;AACb,mBAAK,QAAQ,IAAI,OAAO,OAAO,IAAI;AAAA,YACrC;AAAA,YACA,MAAK;AAAA,YACL,MAAK;AAAA,YACL,gBAAc;AAAA,YACd,UAAU,OAAO;AAAA,YACjB,OAAO,OAAO;AAAA,YAId,UAAU,UAAU,IAAI;AAAA,YACxB,SAAS,MAAM,SAAS,OAAO,KAAK;AAAA,YACpC,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA,QAAQ;AAAA,cACR,UAAU,MAAM,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE;AAAA,YACzC;AAAA,YAEC,iBAAO;AAAA;AAAA,UAtBH,OAAO;AAAA,QAuBd;AAAA,MAEJ,CAAC;AAAA;AAAA,EACH;AAEJ;","names":[]}