@petnow/ui 5.0.0 → 5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.0.1
4
+
5
+ ### Fixes
6
+
7
+ - `@petnow/ui` and `@petnow/ui/v0/tabs` load in Node again (test runners, SSR without a bundler). v0 `Tabs`
8
+ imported `keen-slider/react`, which Node ESM cannot resolve because keen-slider has no `exports` map, and
9
+ `keen-slider/keen-slider.min.css`, which Node cannot import. It now imports `keen-slider/react.js`, and the
10
+ keen-slider styles are Tailwind utilities on the slider elements, so they come from the consumer's Tailwind
11
+ build like every other component class. `dist/index.css` is still optional for `Tabs`.
12
+
13
+ ### Internal
14
+
15
+ - CI imports every built `dist` module with Node (`pnpm check:dist`).
16
+ - `storybook-static/` is git-ignored.
17
+
3
18
  ## 5.0.0
4
19
 
5
20
  Consumers own Tailwind, and the package stops leaking global styles. See
package/dist/v0/tabs.js CHANGED
@@ -2,8 +2,7 @@
2
2
  import { t as e } from "../TailwindUtil-DiNvXuNl.js";
3
3
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
4
4
  import { useEffect as r, useRef as i, useState as a } from "react";
5
- import { useKeenSlider as o } from "keen-slider/react";
6
- import "keen-slider/keen-slider.min.css";
5
+ import { useKeenSlider as o } from "keen-slider/react.js";
7
6
  //#region src/components/v0/tabs/Tabs.tsx
8
7
  var s = ({ className: s, tabList: c, isCuratedcontent: l, unswipeableContent: u, defaultIndex: d = 0, onTabChange: f, disabled: p, allowScrollToSection: m = !0 }) => {
9
8
  let [h, g] = a(d), _ = i(null), v = i(h), y = i(f);
@@ -59,9 +58,9 @@ var s = ({ className: s, tabList: c, isCuratedcontent: l, unswipeableContent: u,
59
58
  u,
60
59
  /* @__PURE__ */ t("div", {
61
60
  ref: b,
62
- className: "keen-slider",
61
+ className: "keen-slider relative flex w-full touch-pan-y content-start overflow-hidden select-none [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none]",
63
62
  children: c.map((e) => /* @__PURE__ */ t("div", {
64
- className: "keen-slider__slide",
63
+ className: "keen-slider__slide relative min-h-full w-full overflow-hidden",
65
64
  children: e.content
66
65
  }, e.key))
67
66
  })
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","names":[],"sources":["../../src/components/v0/tabs/Tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport { ReactNode, useEffect, useRef, useState } from \"react\";\nimport { useKeenSlider } from \"keen-slider/react\";\n\nimport \"keen-slider/keen-slider.min.css\";\n\nimport { cn } from \"../../../utils/TailwindUtil\";\n\ninterface TabItem {\n readonly displayName: string;\n readonly key: string;\n readonly content: ReactNode;\n}\n\ninterface Props<T extends TabItem> {\n tabList: Readonly<T[]>;\n isCuratedcontent?: true;\n unswipeableContent?: ReactNode;\n defaultIndex?: number;\n onTabChange?: (index: number) => void;\n disabled?: boolean;\n className?: {\n tab?: string;\n tabTitle?: string;\n selectedUnderline?: string;\n underline?: string;\n };\n allowScrollToSection?: boolean;\n}\n\nconst Tabs = <T extends TabItem>({\n className,\n tabList,\n isCuratedcontent,\n unswipeableContent,\n defaultIndex = 0,\n onTabChange,\n disabled,\n allowScrollToSection = true,\n}: Props<T>) => {\n const [currentTabIndex, setCurrentTabIndex] = useState<number>(defaultIndex);\n const TabRef = useRef<HTMLDivElement>(null);\n // keen-slider keeps the callbacks it was created with, so they read the latest values from refs.\n const currentTabIndexRef = useRef(currentTabIndex);\n const onTabChangeRef = useRef(onTabChange);\n\n useEffect(() => {\n currentTabIndexRef.current = currentTabIndex;\n onTabChangeRef.current = onTabChange;\n });\n\n // When a swipe is released, keen-slider has already started snapping and `animator.targetIdx`\n // holds the tab it lands on, so the tab changes once per swipe, as with react-swipeable-views.\n const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({\n initial: defaultIndex,\n drag: !disabled,\n dragEnded: (instance) => {\n const index = instance.track.absToRel(instance.animator.targetIdx ?? instance.track.details.abs);\n if (index === currentTabIndexRef.current) return;\n setCurrentTabIndex(index);\n onTabChangeRef.current?.(index);\n },\n });\n\n const scrollToSection = (elementRef: React.RefObject<HTMLDivElement | null>) => {\n if (elementRef.current) {\n window.scrollTo({\n top: elementRef.current.offsetTop - 50,\n behavior: \"smooth\",\n });\n }\n };\n\n const handleTabClick = (index: number) => {\n setCurrentTabIndex(index);\n currentTabIndexRef.current = index;\n if (allowScrollToSection) scrollToSection(TabRef);\n slider.current?.moveToIdx(index);\n onTabChange?.(index);\n };\n\n const underlineStyle = () => {\n const listLength = tabList.length;\n const widthPercent = 100 / listLength;\n return {\n width: `${widthPercent}%`,\n left: `${currentTabIndex * widthPercent}%`,\n };\n };\n\n return (\n <div ref={TabRef} className=\"w-full\">\n <div\n className={cn(\n className?.tab,\n `z-50 mb-[20px] flex w-full flex-col bg-white ${isCuratedcontent && \"sticky top-[50px]\"}`,\n )}\n >\n <div className=\"flex\">\n {tabList.map((tab, index) => (\n <div key={tab.key} className=\"flex flex-1 flex-col\">\n <button\n className={cn(\n className?.tabTitle,\n `cursor-pointer ${\n currentTabIndex === index\n ? \"text-petnow-grey-30 text-label-large\"\n : \"text-petnow-grey-70 text-body-large disabled:opacity-40\"\n }`,\n )}\n onClick={() => handleTabClick(index)}\n disabled={disabled}\n >\n {tab.displayName}\n </button>\n </div>\n ))}\n </div>\n <div\n className={cn(\n className?.underline,\n `relative h-[2px] w-full ${disabled ? \"bg-petnow-grey-70/40\" : \"bg-petnow-grey-70\"}`,\n )}\n >\n <div\n className={cn(\n className?.selectedUnderline,\n \"bg-petnow-grey-30 absolute h-[2px] transition-all duration-200\",\n )}\n style={underlineStyle()}\n />\n </div>\n </div>\n\n {unswipeableContent}\n\n <div ref={sliderRef} className=\"keen-slider\">\n {tabList.map((tab) => (\n <div key={tab.key} className=\"keen-slider__slide\">\n {tab.content}\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Tabs;\n"],"mappings":";;;;;;;AA+BA,IAAM,KAA2B,EAC/B,cACA,YACA,qBACA,uBACA,kBAAe,GACf,gBACA,aACA,0BAAuB,SACT;CACd,IAAM,CAAC,GAAiB,KAAsB,EAAiB,CAAY,GACrE,IAAS,EAAuB,IAAI,GAEpC,IAAqB,EAAO,CAAe,GAC3C,IAAiB,EAAO,CAAW;CAEzC,QAAgB;EAEd,AADA,EAAmB,UAAU,GAC7B,EAAe,UAAU;CAC3B,CAAC;CAID,IAAM,CAAC,GAAW,KAAU,EAA8B;EACxD,SAAS;EACT,MAAM,CAAC;EACP,YAAY,MAAa;GACvB,IAAM,IAAQ,EAAS,MAAM,SAAS,EAAS,SAAS,aAAa,EAAS,MAAM,QAAQ,GAAG;GAC3F,MAAU,EAAmB,YACjC,EAAmB,CAAK,GACxB,EAAe,UAAU,CAAK;EAChC;CACF,CAAC,GAEK,KAAmB,MAAuD;EAC9E,AAAI,EAAW,WACb,OAAO,SAAS;GACd,KAAK,EAAW,QAAQ,YAAY;GACpC,UAAU;EACZ,CAAC;CAEL,GAEM,KAAkB,MAAkB;EAKxC,AAJA,EAAmB,CAAK,GACxB,EAAmB,UAAU,GACzB,KAAsB,EAAgB,CAAM,GAChD,EAAO,SAAS,UAAU,CAAK,GAC/B,IAAc,CAAK;CACrB;CAWA,OACE,kBAAC,OAAD;EAAK,KAAK;EAAQ,WAAU;YAA5B;GACE,kBAAC,OAAD;IACE,WAAW,EACT,GAAW,KACX,gDAAgD,KAAoB,qBACtE;cAJF,CAME,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAQ,KAAK,GAAK,MACjB,kBAAC,OAAD;MAAmB,WAAU;gBAC3B,kBAAC,UAAD;OACE,WAAW,EACT,GAAW,UACX,kBACE,MAAoB,IAChB,yCACA,2DAER;OACA,eAAe,EAAe,CAAK;OACzB;iBAET,EAAI;MACC,CAAA;KACL,GAfK,EAAI,GAeT,CACN;IACE,CAAA,GACL,kBAAC,OAAD;KACE,WAAW,EACT,GAAW,WACX,2BAA2B,IAAW,yBAAyB,qBACjE;eAEA,kBAAC,OAAD;MACE,WAAW,EACT,GAAW,mBACX,gEACF;MACA,cAhDmB;OAE3B,IAAM,IAAe,MADF,EAAQ;OAE3B,OAAO;QACL,OAAO,GAAG,EAAa;QACvB,MAAM,GAAG,IAAkB,EAAa;OAC1C;MACF,EAyCiB,CAAe;KACvB,CAAA;IACE,CAAA,CACF;;GAEJ;GAED,kBAAC,OAAD;IAAK,KAAK;IAAW,WAAU;cAC5B,EAAQ,KAAK,MACZ,kBAAC,OAAD;KAAmB,WAAU;eAC1B,EAAI;IACF,GAFK,EAAI,GAET,CACN;GACE,CAAA;EACF;;AAET"}
1
+ {"version":3,"file":"tabs.js","names":[],"sources":["../../src/components/v0/tabs/Tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport { ReactNode, useEffect, useRef, useState } from \"react\";\n// keen-slider has no `exports` map, so Node ESM needs the full file name. The CommonJS build loads\n// in Node ESM, Jest and bundlers alike; `react.es.js` breaks CommonJS test runners.\nimport { useKeenSlider } from \"keen-slider/react.js\";\n\nimport { cn } from \"../../../utils/TailwindUtil\";\n\ninterface TabItem {\n readonly displayName: string;\n readonly key: string;\n readonly content: ReactNode;\n}\n\ninterface Props<T extends TabItem> {\n tabList: Readonly<T[]>;\n isCuratedcontent?: true;\n unswipeableContent?: ReactNode;\n defaultIndex?: number;\n onTabChange?: (index: number) => void;\n disabled?: boolean;\n className?: {\n tab?: string;\n tabTitle?: string;\n selectedUnderline?: string;\n underline?: string;\n };\n allowScrollToSection?: boolean;\n}\n\nconst Tabs = <T extends TabItem>({\n className,\n tabList,\n isCuratedcontent,\n unswipeableContent,\n defaultIndex = 0,\n onTabChange,\n disabled,\n allowScrollToSection = true,\n}: Props<T>) => {\n const [currentTabIndex, setCurrentTabIndex] = useState<number>(defaultIndex);\n const TabRef = useRef<HTMLDivElement>(null);\n // keen-slider keeps the callbacks it was created with, so they read the latest values from refs.\n const currentTabIndexRef = useRef(currentTabIndex);\n const onTabChangeRef = useRef(onTabChange);\n\n useEffect(() => {\n currentTabIndexRef.current = currentTabIndex;\n onTabChangeRef.current = onTabChange;\n });\n\n // When a swipe is released, keen-slider has already started snapping and `animator.targetIdx`\n // holds the tab it lands on, so the tab changes once per swipe, as with react-swipeable-views.\n const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({\n initial: defaultIndex,\n drag: !disabled,\n dragEnded: (instance) => {\n const index = instance.track.absToRel(instance.animator.targetIdx ?? instance.track.details.abs);\n if (index === currentTabIndexRef.current) return;\n setCurrentTabIndex(index);\n onTabChangeRef.current?.(index);\n },\n });\n\n const scrollToSection = (elementRef: React.RefObject<HTMLDivElement | null>) => {\n if (elementRef.current) {\n window.scrollTo({\n top: elementRef.current.offsetTop - 50,\n behavior: \"smooth\",\n });\n }\n };\n\n const handleTabClick = (index: number) => {\n setCurrentTabIndex(index);\n currentTabIndexRef.current = index;\n if (allowScrollToSection) scrollToSection(TabRef);\n slider.current?.moveToIdx(index);\n onTabChange?.(index);\n };\n\n const underlineStyle = () => {\n const listLength = tabList.length;\n const widthPercent = 100 / listLength;\n return {\n width: `${widthPercent}%`,\n left: `${currentTabIndex * widthPercent}%`,\n };\n };\n\n return (\n <div ref={TabRef} className=\"w-full\">\n <div\n className={cn(\n className?.tab,\n `z-50 mb-[20px] flex w-full flex-col bg-white ${isCuratedcontent && \"sticky top-[50px]\"}`,\n )}\n >\n <div className=\"flex\">\n {tabList.map((tab, index) => (\n <div key={tab.key} className=\"flex flex-1 flex-col\">\n <button\n className={cn(\n className?.tabTitle,\n `cursor-pointer ${\n currentTabIndex === index\n ? \"text-petnow-grey-30 text-label-large\"\n : \"text-petnow-grey-70 text-body-large disabled:opacity-40\"\n }`,\n )}\n onClick={() => handleTabClick(index)}\n disabled={disabled}\n >\n {tab.displayName}\n </button>\n </div>\n ))}\n </div>\n <div\n className={cn(\n className?.underline,\n `relative h-[2px] w-full ${disabled ? \"bg-petnow-grey-70/40\" : \"bg-petnow-grey-70\"}`,\n )}\n >\n <div\n className={cn(\n className?.selectedUnderline,\n \"bg-petnow-grey-30 absolute h-[2px] transition-all duration-200\",\n )}\n style={underlineStyle()}\n />\n </div>\n </div>\n\n {unswipeableContent}\n\n {/*\n keen-slider.min.css as utilities, so the consumer's Tailwind build emits them and Node never\n imports CSS. Tabs never sets the reverse or vertical options, so their rules are left out.\n */}\n <div\n ref={sliderRef}\n className=\"keen-slider relative flex w-full touch-pan-y content-start overflow-hidden select-none [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none]\"\n >\n {tabList.map((tab) => (\n <div key={tab.key} className=\"keen-slider__slide relative min-h-full w-full overflow-hidden\">\n {tab.content}\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Tabs;\n"],"mappings":";;;;;;AA+BA,IAAM,KAA2B,EAC/B,cACA,YACA,qBACA,uBACA,kBAAe,GACf,gBACA,aACA,0BAAuB,SACT;CACd,IAAM,CAAC,GAAiB,KAAsB,EAAiB,CAAY,GACrE,IAAS,EAAuB,IAAI,GAEpC,IAAqB,EAAO,CAAe,GAC3C,IAAiB,EAAO,CAAW;CAEzC,QAAgB;EAEd,AADA,EAAmB,UAAU,GAC7B,EAAe,UAAU;CAC3B,CAAC;CAID,IAAM,CAAC,GAAW,KAAU,EAA8B;EACxD,SAAS;EACT,MAAM,CAAC;EACP,YAAY,MAAa;GACvB,IAAM,IAAQ,EAAS,MAAM,SAAS,EAAS,SAAS,aAAa,EAAS,MAAM,QAAQ,GAAG;GAC3F,MAAU,EAAmB,YACjC,EAAmB,CAAK,GACxB,EAAe,UAAU,CAAK;EAChC;CACF,CAAC,GAEK,KAAmB,MAAuD;EAC9E,AAAI,EAAW,WACb,OAAO,SAAS;GACd,KAAK,EAAW,QAAQ,YAAY;GACpC,UAAU;EACZ,CAAC;CAEL,GAEM,KAAkB,MAAkB;EAKxC,AAJA,EAAmB,CAAK,GACxB,EAAmB,UAAU,GACzB,KAAsB,EAAgB,CAAM,GAChD,EAAO,SAAS,UAAU,CAAK,GAC/B,IAAc,CAAK;CACrB;CAWA,OACE,kBAAC,OAAD;EAAK,KAAK;EAAQ,WAAU;YAA5B;GACE,kBAAC,OAAD;IACE,WAAW,EACT,GAAW,KACX,gDAAgD,KAAoB,qBACtE;cAJF,CAME,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAQ,KAAK,GAAK,MACjB,kBAAC,OAAD;MAAmB,WAAU;gBAC3B,kBAAC,UAAD;OACE,WAAW,EACT,GAAW,UACX,kBACE,MAAoB,IAChB,yCACA,2DAER;OACA,eAAe,EAAe,CAAK;OACzB;iBAET,EAAI;MACC,CAAA;KACL,GAfK,EAAI,GAeT,CACN;IACE,CAAA,GACL,kBAAC,OAAD;KACE,WAAW,EACT,GAAW,WACX,2BAA2B,IAAW,yBAAyB,qBACjE;eAEA,kBAAC,OAAD;MACE,WAAW,EACT,GAAW,mBACX,gEACF;MACA,cAhDmB;OAE3B,IAAM,IAAe,MADF,EAAQ;OAE3B,OAAO;QACL,OAAO,GAAG,EAAa;QACvB,MAAM,GAAG,IAAkB,EAAa;OAC1C;MACF,EAyCiB,CAAe;KACvB,CAAA;IACE,CAAA,CACF;;GAEJ;GAMD,kBAAC,OAAD;IACE,KAAK;IACL,WAAU;cAET,EAAQ,KAAK,MACZ,kBAAC,OAAD;KAAmB,WAAU;eAC1B,EAAI;IACF,GAFK,EAAI,GAET,CACN;GACE,CAAA;EACF;;AAET"}
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@petnow/ui",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@11.1.3",
6
6
  "scripts": {
7
7
  "build": "tsc && vite build && pnpm run build:css",
8
8
  "build:css": "node -e \"require('fs').copyFileSync('src/styles/components.css', 'dist/index.css')\"",
9
+ "check:dist": "node scripts/check-dist-node.mjs",
9
10
  "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10
11
  "lint:fix": "eslint . --ext ts,tsx --fix",
11
12
  "storybook": "storybook dev -p 6006",