@abumble/design-system 0.0.38 → 0.0.39

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 (39) hide show
  1. package/dist/components/Banner/Banner.d.ts.map +1 -1
  2. package/dist/components/Banner.js.map +1 -1
  3. package/dist/components/Select.js +2 -22
  4. package/dist/components/Select.js.map +1 -1
  5. package/dist/components/ThemeSelector/ThemeSelector.d.ts +2 -0
  6. package/dist/components/ThemeSelector/ThemeSelector.d.ts.map +1 -0
  7. package/dist/components/ThemeSelector/index.d.ts +2 -0
  8. package/dist/components/ThemeSelector/index.d.ts.map +1 -0
  9. package/dist/components/ThemeSelector.js +24 -0
  10. package/dist/components/ThemeSelector.js.map +1 -0
  11. package/dist/components/ThemeToggle/ThemeToggle.d.ts +2 -0
  12. package/dist/components/ThemeToggle/ThemeToggle.d.ts.map +1 -0
  13. package/dist/components/ThemeToggle/index.d.ts +2 -0
  14. package/dist/components/ThemeToggle/index.d.ts.map +1 -0
  15. package/dist/components/ThemeToggle.js +24 -0
  16. package/dist/components/ThemeToggle.js.map +1 -0
  17. package/dist/index.css +1 -0
  18. package/dist/shared/Select.js +25 -0
  19. package/dist/shared/Select.js.map +1 -0
  20. package/dist/shared/useTheme.js +12 -0
  21. package/dist/shared/useTheme.js.map +1 -0
  22. package/dist/themes/ThemeContext.d.ts +10 -0
  23. package/dist/themes/ThemeContext.d.ts.map +1 -0
  24. package/dist/themes/ThemeProvider.d.ts +9 -0
  25. package/dist/themes/ThemeProvider.d.ts.map +1 -0
  26. package/dist/themes/index.d.ts +3 -0
  27. package/dist/themes/index.d.ts.map +1 -0
  28. package/dist/themes/theme.d.ts +2 -0
  29. package/dist/themes/theme.d.ts.map +1 -0
  30. package/dist/themes/useTheme.d.ts +2 -0
  31. package/dist/themes/useTheme.d.ts.map +1 -0
  32. package/dist/themes.js +50 -0
  33. package/dist/themes.js.map +1 -0
  34. package/package.json +8 -136
  35. package/src/themes/ThemeContext.ts +12 -0
  36. package/src/themes/ThemeProvider.tsx +86 -0
  37. package/src/themes/index.ts +2 -0
  38. package/src/themes/theme.tsx +3 -0
  39. package/src/themes/useTheme.ts +8 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../../src/components/Banner/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAU3D,UAAU,WAAY,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACxD,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,OAAO,CAAC,EAAE,eAAe,CAAC,iBAAiB,CAAC,CAAA;CAC5C;AAED,iBAAS,MAAM,CAAC,EACf,IAAI,EACJ,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACR,EAAE,WAAW,2CA+Bb;AAED,UAAU,kBAAmB,SAAQ,WAAW;IAC/C,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAA;CACjC;AAED,iBAAS,aAAa,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,2CAM/D;AA4BD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../../src/components/Banner/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAa3D,UAAU,WAAY,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACxD,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,OAAO,CAAC,EAAE,eAAe,CAAC,iBAAiB,CAAC,CAAA;CAC5C;AAED,iBAAS,MAAM,CAAC,EACf,IAAI,EACJ,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACR,EAAE,WAAW,2CA+Bb;AAED,UAAU,kBAAmB,SAAQ,WAAW;IAC/C,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAA;CACjC;AAED,iBAAS,aAAa,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,2CAM/D;AA4BD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.js","sources":["../../src/components/Banner/bannerType.ts","../../src/components/Banner/Banner.tsx"],"sourcesContent":["const bannerType = {\n\tInfo: 'info',\n\tNote: 'note',\n\tWarning: 'warning',\n\tAlert: 'alert'\n} as const;\n\ntype TBannerType = (typeof bannerType)[keyof typeof bannerType];\n\nexport { bannerType, type TBannerType };\n","import type { onClickCallback } from '@/types/types'\nimport { cn } from '@/utils'\nimport { CircleX, Info, Lightbulb, TriangleAlert, X } from 'lucide-react'\nimport type React from 'react'\nimport { Button } from '../Button'\nimport { Skeleton } from '../Skeleton'\nimport { bannerType, type TBannerType } from './bannerType'\n\n/** Banner colors and layout are in design-system styles.css via [data-banner-type]. Type → color: info=blue, note=green, warning=yellow, alert=red. */\nconst icons: Record<TBannerType, React.ComponentType<{ className?: string }>> = {\n\t[bannerType.Info]: Info,\n\t[bannerType.Note]: Lightbulb,\n\t[bannerType.Warning]: TriangleAlert,\n\t[bannerType.Alert]: CircleX,\n}\n\ninterface BannerProps extends React.ComponentProps<'div'> {\n\ttype: TBannerType\n\ttitle?: string\n\tloading?: boolean\n\thideIcon?: boolean\n\ticon?: React.ComponentType<{ className?: string }>\n\tonClose?: onClickCallback<HTMLButtonElement>\n}\n\nfunction Banner({\n\ttype,\n\ttitle,\n\tloading,\n\ticon,\n\thideIcon,\n\tonClose,\n\tchildren,\n\tclassName,\n\t...props\n}: BannerProps) {\n\tconst Icon = icon ?? icons[type] ?? icons[bannerType.Note]\n\n\treturn (\n\t\t<div\n\t\t\tdata-banner-type={type}\n\t\t\tclassName={cn(className)}\n\t\t\trole=\"alert\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<div className=\"flex items-start\">\n\t\t\t\t{loading ? (\n\t\t\t\t\t<BannerLoadingContent />\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{!hideIcon && (\n\t\t\t\t\t\t\t<div className=\"shrink-0 mr-3\">\n\t\t\t\t\t\t\t\t<Icon />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<section>\n\t\t\t\t\t\t\t{title && <p className=\"font-bold\">{title}</p>}\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</section>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\n\t\t\t\t{onClose && <CloseButton onClick={onClose} />}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\ninterface MessageBannerProps extends BannerProps {\n\tmessage: string | React.ReactNode\n}\n\nfunction MessageBanner({ message, ...props }: MessageBannerProps) {\n\treturn (\n\t\t<Banner {...props}>\n\t\t\t<p className=\"text-sm\">{message}</p>\n\t\t</Banner>\n\t)\n}\n\nfunction BannerLoadingContent() {\n\treturn (\n\t\t<div className=\"flex items-center space-x-4\">\n\t\t\t<Skeleton className=\"h-12 w-12 rounded-full\" />\n\t\t\t<div className=\"space-y-2\">\n\t\t\t\t<Skeleton className=\"h-4 w-[250px]\" />\n\t\t\t\t<Skeleton className=\"h-4 w-[200px]\" />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction CloseButton(props: React.ComponentProps<'button'>) {\n\treturn (\n\t\t<Button\n\t\t\tvariant=\"ghost\"\n\t\t\tsize=\"icon\"\n\t\t\tclassName=\"h-8 w-8 rounded-full ml-auto mb-auto relative -top-1 -right-1\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<X />\n\t\t\t<span className=\"sr-only\">Close banner</span>\n\t\t</Button>\n\t)\n}\n\nexport { Banner, MessageBanner }\n"],"names":["bannerType","icons","Info","Lightbulb","TriangleAlert","CircleX","Banner","type","title","loading","icon","hideIcon","onClose","children","className","props","Icon","jsx","cn","jsxs","BannerLoadingContent","Fragment","CloseButton","MessageBanner","message","Skeleton","Button","X"],"mappings":";;;;;AAAA,MAAMA,IAAa;AAAA,EAClB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AACR,GCIMC,IAA0E;AAAA,EAC/E,CAACD,EAAW,IAAI,GAAGE;AAAA,EACnB,CAACF,EAAW,IAAI,GAAGG;AAAA,EACnB,CAACH,EAAW,OAAO,GAAGI;AAAA,EACtB,CAACJ,EAAW,KAAK,GAAGK;AACrB;AAWA,SAASC,EAAO;AAAA,EACf,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,MAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,GAAGC;AACJ,GAAgB;AACf,QAAMC,IAAON,KAAQT,EAAMM,CAAI,KAAKN,EAAMD,EAAW,IAAI;AAEzD,SACC,gBAAAiB;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,oBAAkBV;AAAA,MAClB,WAAWW,EAAGJ,CAAS;AAAA,MACvB,MAAK;AAAA,MACJ,GAAGC;AAAA,MAEJ,UAAA,gBAAAI,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,QAAAV,IACA,gBAAAQ,EAACG,GAAA,CAAA,CAAqB,IAEtB,gBAAAD,EAAAE,GAAA,EACE,UAAA;AAAA,UAAA,CAACV,KACD,gBAAAM,EAAC,OAAA,EAAI,WAAU,iBACd,UAAA,gBAAAA,EAACD,KAAK,EAAA,CACP;AAAA,4BAEA,WAAA,EACC,UAAA;AAAA,YAAAR,KAAS,gBAAAS,EAAC,KAAA,EAAE,WAAU,aAAa,UAAAT,GAAM;AAAA,YACzCK;AAAA,UAAA,EAAA,CACF;AAAA,QAAA,GACD;AAAA,QAGAD,KAAW,gBAAAK,EAACK,GAAA,EAAY,SAASV,EAAA,CAAS;AAAA,MAAA,EAAA,CAC5C;AAAA,IAAA;AAAA,EAAA;AAGH;AAMA,SAASW,EAAc,EAAE,SAAAC,GAAS,GAAGT,KAA6B;AACjE,SACC,gBAAAE,EAACX,KAAQ,GAAGS,GACX,4BAAC,KAAA,EAAE,WAAU,WAAW,UAAAS,EAAA,CAAQ,EAAA,CACjC;AAEF;AAEA,SAASJ,IAAuB;AAC/B,SACC,gBAAAD,EAAC,OAAA,EAAI,WAAU,+BACd,UAAA;AAAA,IAAA,gBAAAF,EAACQ,GAAA,EAAS,WAAU,yBAAA,CAAyB;AAAA,IAC7C,gBAAAN,EAAC,OAAA,EAAI,WAAU,aACd,UAAA;AAAA,MAAA,gBAAAF,EAACQ,GAAA,EAAS,WAAU,gBAAA,CAAgB;AAAA,MACpC,gBAAAR,EAACQ,GAAA,EAAS,WAAU,gBAAA,CAAgB;AAAA,IAAA,EAAA,CACrC;AAAA,EAAA,GACD;AAEF;AAEA,SAASH,EAAYP,GAAuC;AAC3D,SACC,gBAAAI;AAAA,IAACO;AAAA,IAAA;AAAA,MACA,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,WAAU;AAAA,MACT,GAAGX;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAE,EAACU,GAAA,EAAE;AAAA,QACH,gBAAAV,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,eAAA,CAAY;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGzC;"}
1
+ {"version":3,"file":"Banner.js","sources":["../../src/components/Banner/bannerType.ts","../../src/components/Banner/Banner.tsx"],"sourcesContent":["const bannerType = {\n\tInfo: 'info',\n\tNote: 'note',\n\tWarning: 'warning',\n\tAlert: 'alert'\n} as const;\n\ntype TBannerType = (typeof bannerType)[keyof typeof bannerType];\n\nexport { bannerType, type TBannerType };\n","import type { onClickCallback } from '@/types/types'\nimport { cn } from '@/utils'\nimport { CircleX, Info, Lightbulb, TriangleAlert, X } from 'lucide-react'\nimport type React from 'react'\nimport { Button } from '../Button'\nimport { Skeleton } from '../Skeleton'\nimport { bannerType, type TBannerType } from './bannerType'\n\n/** Banner colors and layout are in design-system styles.css via [data-banner-type]. Type → color: info=blue, note=green, warning=yellow, alert=red. */\nconst icons: Record<\n\tTBannerType,\n\tReact.ComponentType<{ className?: string }>\n> = {\n\t[bannerType.Info]: Info,\n\t[bannerType.Note]: Lightbulb,\n\t[bannerType.Warning]: TriangleAlert,\n\t[bannerType.Alert]: CircleX,\n}\n\ninterface BannerProps extends React.ComponentProps<'div'> {\n\ttype: TBannerType\n\ttitle?: string\n\tloading?: boolean\n\thideIcon?: boolean\n\ticon?: React.ComponentType<{ className?: string }>\n\tonClose?: onClickCallback<HTMLButtonElement>\n}\n\nfunction Banner({\n\ttype,\n\ttitle,\n\tloading,\n\ticon,\n\thideIcon,\n\tonClose,\n\tchildren,\n\tclassName,\n\t...props\n}: BannerProps) {\n\tconst Icon = icon ?? icons[type] ?? icons[bannerType.Note]\n\n\treturn (\n\t\t<div\n\t\t\tdata-banner-type={type}\n\t\t\tclassName={cn(className)}\n\t\t\trole=\"alert\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<div className=\"flex items-start\">\n\t\t\t\t{loading ? (\n\t\t\t\t\t<BannerLoadingContent />\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{!hideIcon && (\n\t\t\t\t\t\t\t<div className=\"shrink-0 mr-3\">\n\t\t\t\t\t\t\t\t<Icon />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<section>\n\t\t\t\t\t\t\t{title && <p className=\"font-bold\">{title}</p>}\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</section>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\n\t\t\t\t{onClose && <CloseButton onClick={onClose} />}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\ninterface MessageBannerProps extends BannerProps {\n\tmessage: string | React.ReactNode\n}\n\nfunction MessageBanner({ message, ...props }: MessageBannerProps) {\n\treturn (\n\t\t<Banner {...props}>\n\t\t\t<p className=\"text-sm\">{message}</p>\n\t\t</Banner>\n\t)\n}\n\nfunction BannerLoadingContent() {\n\treturn (\n\t\t<div className=\"flex items-center space-x-4\">\n\t\t\t<Skeleton className=\"h-12 w-12 rounded-full\" />\n\t\t\t<div className=\"space-y-2\">\n\t\t\t\t<Skeleton className=\"h-4 w-[250px]\" />\n\t\t\t\t<Skeleton className=\"h-4 w-[200px]\" />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction CloseButton(props: React.ComponentProps<'button'>) {\n\treturn (\n\t\t<Button\n\t\t\tvariant=\"ghost\"\n\t\t\tsize=\"icon\"\n\t\t\tclassName=\"h-8 w-8 rounded-full ml-auto mb-auto relative -top-1 -right-1\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<X />\n\t\t\t<span className=\"sr-only\">Close banner</span>\n\t\t</Button>\n\t)\n}\n\nexport { Banner, MessageBanner }\n"],"names":["bannerType","icons","Info","Lightbulb","TriangleAlert","CircleX","Banner","type","title","loading","icon","hideIcon","onClose","children","className","props","Icon","jsx","cn","jsxs","BannerLoadingContent","Fragment","CloseButton","MessageBanner","message","Skeleton","Button","X"],"mappings":";;;;;AAAA,MAAMA,IAAa;AAAA,EAClB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AACR,GCIMC,IAGF;AAAA,EACH,CAACD,EAAW,IAAI,GAAGE;AAAA,EACnB,CAACF,EAAW,IAAI,GAAGG;AAAA,EACnB,CAACH,EAAW,OAAO,GAAGI;AAAA,EACtB,CAACJ,EAAW,KAAK,GAAGK;AACrB;AAWA,SAASC,EAAO;AAAA,EACf,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,MAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,GAAGC;AACJ,GAAgB;AACf,QAAMC,IAAON,KAAQT,EAAMM,CAAI,KAAKN,EAAMD,EAAW,IAAI;AAEzD,SACC,gBAAAiB;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,oBAAkBV;AAAA,MAClB,WAAWW,EAAGJ,CAAS;AAAA,MACvB,MAAK;AAAA,MACJ,GAAGC;AAAA,MAEJ,UAAA,gBAAAI,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,QAAAV,IACA,gBAAAQ,EAACG,GAAA,CAAA,CAAqB,IAEtB,gBAAAD,EAAAE,GAAA,EACE,UAAA;AAAA,UAAA,CAACV,KACD,gBAAAM,EAAC,OAAA,EAAI,WAAU,iBACd,UAAA,gBAAAA,EAACD,KAAK,EAAA,CACP;AAAA,4BAEA,WAAA,EACC,UAAA;AAAA,YAAAR,KAAS,gBAAAS,EAAC,KAAA,EAAE,WAAU,aAAa,UAAAT,GAAM;AAAA,YACzCK;AAAA,UAAA,EAAA,CACF;AAAA,QAAA,GACD;AAAA,QAGAD,KAAW,gBAAAK,EAACK,GAAA,EAAY,SAASV,EAAA,CAAS;AAAA,MAAA,EAAA,CAC5C;AAAA,IAAA;AAAA,EAAA;AAGH;AAMA,SAASW,EAAc,EAAE,SAAAC,GAAS,GAAGT,KAA6B;AACjE,SACC,gBAAAE,EAACX,KAAQ,GAAGS,GACX,4BAAC,KAAA,EAAE,WAAU,WAAW,UAAAS,EAAA,CAAQ,EAAA,CACjC;AAEF;AAEA,SAASJ,IAAuB;AAC/B,SACC,gBAAAD,EAAC,OAAA,EAAI,WAAU,+BACd,UAAA;AAAA,IAAA,gBAAAF,EAACQ,GAAA,EAAS,WAAU,yBAAA,CAAyB;AAAA,IAC7C,gBAAAN,EAAC,OAAA,EAAI,WAAU,aACd,UAAA;AAAA,MAAA,gBAAAF,EAACQ,GAAA,EAAS,WAAU,gBAAA,CAAgB;AAAA,MACpC,gBAAAR,EAACQ,GAAA,EAAS,WAAU,gBAAA,CAAgB;AAAA,IAAA,EAAA,CACrC;AAAA,EAAA,GACD;AAEF;AAEA,SAASH,EAAYP,GAAuC;AAC3D,SACC,gBAAAI;AAAA,IAACO;AAAA,IAAA;AAAA,MACA,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,WAAU;AAAA,MACT,GAAGX;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAE,EAACU,GAAA,EAAE;AAAA,QACH,gBAAAV,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,eAAA,CAAY;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGzC;"}
@@ -1,25 +1,5 @@
1
- import { jsx as r } from "react/jsx-runtime";
2
- import "react";
3
- import { c as i } from "../shared/utils.js";
4
- function l({
5
- className: e,
6
- ...o
7
- }) {
8
- return /* @__PURE__ */ r(
9
- "select",
10
- {
11
- "data-slot": "select",
12
- className: i(
13
- "flex h-9 w-full rounded border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors outline-none",
14
- "focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:border-ring",
15
- "disabled:pointer-events-none disabled:opacity-50",
16
- e
17
- ),
18
- ...o
19
- }
20
- );
21
- }
1
+ import { S as r } from "../shared/Select.js";
22
2
  export {
23
- l as Select
3
+ r as Select
24
4
  };
25
5
  //# sourceMappingURL=Select.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","sources":["../../src/components/Select/Select.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport { cn } from '@/utils'\n\n/** Native select styled to match design-system Input (form control). */\nexport function Select({\n\tclassName,\n\t...props\n}: React.ComponentProps<'select'>) {\n\treturn (\n\t\t<select\n\t\t\tdata-slot=\"select\"\n\t\t\tclassName={cn(\n\t\t\t\t'flex h-9 w-full rounded border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors outline-none',\n\t\t\t\t'focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:border-ring',\n\t\t\t\t'disabled:pointer-events-none disabled:opacity-50',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n"],"names":["Select","className","props","jsx","cn"],"mappings":";;;AAKO,SAASA,EAAO;AAAA,EACtB,WAAAC;AAAA,EACA,GAAGC;AACJ,GAAmC;AAClC,SACC,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,aAAU;AAAA,MACV,WAAWC;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACAH;AAAA,MAAA;AAAA,MAEA,GAAGC;AAAA,IAAA;AAAA,EAAA;AAGP;"}
1
+ {"version":3,"file":"Select.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,2 @@
1
+ export declare function ThemeSelector(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=ThemeSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeSelector.d.ts","sourceRoot":"","sources":["../../../src/components/ThemeSelector/ThemeSelector.tsx"],"names":[],"mappings":"AASA,wBAAgB,aAAa,4CAe5B"}
@@ -0,0 +1,2 @@
1
+ export { ThemeSelector } from './ThemeSelector';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ThemeSelector/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,24 @@
1
+ import { jsx as o } from "react/jsx-runtime";
2
+ import "react";
3
+ import { u as n } from "../shared/useTheme.js";
4
+ import { S as a } from "../shared/Select.js";
5
+ const m = [
6
+ { value: "linen", label: "Linen" },
7
+ { value: "steel", label: "Steel" }
8
+ ];
9
+ function p() {
10
+ const { colorTheme: l, setColorTheme: t } = n();
11
+ return /* @__PURE__ */ o(
12
+ a,
13
+ {
14
+ value: l,
15
+ "aria-label": "Select color theme",
16
+ onChange: (e) => t(e.target.value),
17
+ children: m.map(({ value: e, label: r }) => /* @__PURE__ */ o("option", { value: e, children: r }, e))
18
+ }
19
+ );
20
+ }
21
+ export {
22
+ p as ThemeSelector
23
+ };
24
+ //# sourceMappingURL=ThemeSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeSelector.js","sources":["../../src/components/ThemeSelector/ThemeSelector.tsx"],"sourcesContent":["import { useTheme } from '@/themes'\nimport type { ColorTheme } from '@/themes'\nimport { Select } from '../Select'\n\nconst COLOR_THEMES: { value: ColorTheme; label: string }[] = [\n\t{ value: 'linen', label: 'Linen' },\n\t{ value: 'steel', label: 'Steel' },\n]\n\nexport function ThemeSelector() {\n\tconst { colorTheme, setColorTheme } = useTheme()\n\treturn (\n\t\t<Select\n\t\t\tvalue={colorTheme}\n\t\t\taria-label=\"Select color theme\"\n\t\t\tonChange={(e) => setColorTheme(e.target.value as ColorTheme)}\n\t\t>\n\t\t\t{COLOR_THEMES.map(({ value, label }) => (\n\t\t\t\t<option key={value} value={value}>\n\t\t\t\t\t{label}\n\t\t\t\t</option>\n\t\t\t))}\n\t\t</Select>\n\t)\n}\n"],"names":["COLOR_THEMES","ThemeSelector","colorTheme","setColorTheme","useTheme","jsx","Select","value","label"],"mappings":";;;;AAIA,MAAMA,IAAuD;AAAA,EAC5D,EAAE,OAAO,SAAS,OAAO,QAAA;AAAA,EACzB,EAAE,OAAO,SAAS,OAAO,QAAA;AAC1B;AAEO,SAASC,IAAgB;AAC/B,QAAM,EAAE,YAAAC,GAAY,eAAAC,EAAA,IAAkBC,EAAA;AACtC,SACC,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACA,OAAOJ;AAAA,MACP,cAAW;AAAA,MACX,UAAU,CAAC,MAAMC,EAAc,EAAE,OAAO,KAAmB;AAAA,MAE1D,UAAAH,EAAa,IAAI,CAAC,EAAE,OAAAO,GAAO,OAAAC,EAAA,MAC3B,gBAAAH,EAAC,UAAA,EAAmB,OAAAE,GAClB,UAAAC,EAAA,GADWD,CAEb,CACA;AAAA,IAAA;AAAA,EAAA;AAGJ;"}
@@ -0,0 +1,2 @@
1
+ export declare function ThemeToggle(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=ThemeToggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../../src/components/ThemeToggle/ThemeToggle.tsx"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,4CAgB1B"}
@@ -0,0 +1,2 @@
1
+ export { ThemeToggle } from './ThemeToggle';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ThemeToggle/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,24 @@
1
+ import { jsx as o } from "react/jsx-runtime";
2
+ import "react";
3
+ import { u as s } from "../shared/useTheme.js";
4
+ import { Moon as a, Sun as m } from "lucide-react";
5
+ import { B as i } from "../shared/Button.js";
6
+ function d() {
7
+ const { setTheme: t, effectiveTheme: r } = s(), e = r === "dark";
8
+ return /* @__PURE__ */ o(
9
+ i,
10
+ {
11
+ type: "button",
12
+ variant: "ghost",
13
+ size: "icon",
14
+ className: "rounded-full",
15
+ "aria-label": e ? "Dark mode on" : "Dark mode off",
16
+ onClick: () => t(e ? "light" : "dark"),
17
+ children: e ? /* @__PURE__ */ o(a, { className: "size-5" }) : /* @__PURE__ */ o(m, { className: "size-5" })
18
+ }
19
+ );
20
+ }
21
+ export {
22
+ d as ThemeToggle
23
+ };
24
+ //# sourceMappingURL=ThemeToggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeToggle.js","sources":["../../src/components/ThemeToggle/ThemeToggle.tsx"],"sourcesContent":["import { useTheme } from '@/themes'\nimport { Moon, Sun } from 'lucide-react'\nimport { Button } from '../Button'\n\nexport function ThemeToggle() {\n\tconst { setTheme, effectiveTheme } = useTheme()\n\tconst isDark = effectiveTheme === 'dark'\n\tconst toggle = () => setTheme(isDark ? 'light' : 'dark')\n\treturn (\n\t\t<Button\n\t\t\ttype=\"button\"\n\t\t\tvariant=\"ghost\"\n\t\t\tsize=\"icon\"\n\t\t\tclassName=\"rounded-full\"\n\t\t\taria-label={isDark ? 'Dark mode on' : 'Dark mode off'}\n\t\t\tonClick={toggle}\n\t\t>\n\t\t\t{isDark ? <Moon className=\"size-5\" /> : <Sun className=\"size-5\" />}\n\t\t</Button>\n\t)\n}\n"],"names":["ThemeToggle","setTheme","effectiveTheme","useTheme","isDark","jsx","Button","Moon","Sun"],"mappings":";;;;;AAIO,SAASA,IAAc;AAC7B,QAAM,EAAE,UAAAC,GAAU,gBAAAC,EAAA,IAAmBC,EAAA,GAC/BC,IAASF,MAAmB;AAElC,SACC,gBAAAG;AAAA,IAACC;AAAA,IAAA;AAAA,MACA,MAAK;AAAA,MACL,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,WAAU;AAAA,MACV,cAAYF,IAAS,iBAAiB;AAAA,MACtC,SARa,MAAMH,EAASG,IAAS,UAAU,MAAM;AAAA,MAUpD,UAAAA,sBAAUG,GAAA,EAAK,WAAU,UAAS,IAAK,gBAAAF,EAACG,GAAA,EAAI,WAAU,SAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AAGnE;"}
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ :root{--background: oklch(.992 .003 85);--foreground: oklch(.2 .01 85);--card: oklch(1 0 0 / .75);--card-foreground: oklch(.2 .01 85);--popover: oklch(1 0 0);--popover-foreground: oklch(.2 .01 85);--primary: oklch(.18 .01 85);--primary-foreground: oklch(1 0 0);--secondary: oklch(1 0 0);--secondary-foreground: oklch(.18 .01 85);--muted: oklch(1 0 0);--muted-foreground: oklch(.5 .01 85);--accent: oklch(1 0 0);--accent-foreground: oklch(.18 .01 85);--destructive: oklch(.55 .15 25);--destructive-foreground: oklch(1 0 0);--border: oklch(.94 .005 85);--input: oklch(.94 .005 85);--ring: oklch(.18 .01 85 / .1);--radius: .6rem;--sidebar: oklch(.995 .002 85);--sidebar-foreground: oklch(.2 .01 85);--sidebar-primary: oklch(.18 .01 85);--sidebar-primary-foreground: oklch(1 0 0);--sidebar-accent: oklch(.97 .01 85);--sidebar-accent-foreground: oklch(.18 .01 85);--sidebar-border: oklch(.95 .005 85);--banner-info: oklch(.94 .02 240);--banner-info-foreground: oklch(.4 .1 240);--banner-info-border: oklch(.85 .05 240);--banner-note: oklch(.94 .02 160);--banner-note-foreground: oklch(.35 .1 160);--banner-note-border: oklch(.85 .05 160);--banner-warning: oklch(.95 .03 80);--banner-warning-foreground: oklch(.45 .1 60);--banner-warning-border: oklch(.88 .05 70);--banner-alert: oklch(.95 .03 25);--banner-alert-foreground: oklch(.45 .12 25);--banner-alert-border: oklch(.88 .08 25);--badge-success: oklch(.4 .1 160);--badge-success-foreground: oklch(1 0 0);--checkbox-checked: oklch(.15 .01 60);--checkbox-checked-foreground: oklch(1 0 0);--checkbox-unchecked-bg: oklch(1 0 0);--checkbox-unchecked-border: oklch(.88 .01 60)}[data-theme=linen]{--background: oklch(.992 .003 85);--foreground: oklch(.2 .01 85);--card: oklch(1 0 0 / .75);--card-foreground: oklch(.2 .01 85);--popover: oklch(1 0 0);--popover-foreground: oklch(.2 .01 85);--primary: oklch(.18 .01 85);--primary-foreground: oklch(1 0 0);--secondary: oklch(1 0 0);--secondary-foreground: oklch(.18 .01 85);--muted: oklch(1 0 0);--muted-foreground: oklch(.5 .01 85);--accent: oklch(1 0 0);--accent-foreground: oklch(.18 .01 85);--destructive: oklch(.55 .15 25);--destructive-foreground: oklch(1 0 0);--border: oklch(.94 .005 85);--input: oklch(.94 .005 85);--ring: oklch(.18 .01 85 / .1);--radius: .6rem;--sidebar: oklch(.995 .002 85);--sidebar-foreground: oklch(.2 .01 85);--sidebar-primary: oklch(.18 .01 85);--sidebar-primary-foreground: oklch(1 0 0);--sidebar-accent: oklch(.97 .01 85);--sidebar-accent-foreground: oklch(.18 .01 85);--sidebar-border: oklch(.95 .005 85);--banner-info: oklch(.94 .02 240);--banner-info-foreground: oklch(.4 .1 240);--banner-info-border: oklch(.85 .05 240);--banner-note: oklch(.94 .02 160);--banner-note-foreground: oklch(.35 .1 160);--banner-note-border: oklch(.85 .05 160);--banner-warning: oklch(.95 .03 80);--banner-warning-foreground: oklch(.45 .1 60);--banner-warning-border: oklch(.88 .05 70);--banner-alert: oklch(.95 .03 25);--banner-alert-foreground: oklch(.45 .12 25);--banner-alert-border: oklch(.88 .08 25);--badge-success: oklch(.4 .1 160);--badge-success-foreground: oklch(1 0 0);--checkbox-checked: oklch(.15 .01 60);--checkbox-checked-foreground: oklch(1 0 0);--checkbox-unchecked-bg: oklch(1 0 0);--checkbox-unchecked-border: oklch(.88 .01 60)}.dark,[data-theme=linen].dark{--background: oklch(.14 .01 80);--foreground: oklch(.93 .01 85);--card: oklch(.19 .012 80 / .75);--card-foreground: oklch(.93 .01 85);--popover: oklch(.17 .01 80);--popover-foreground: oklch(.93 .01 85);--primary: oklch(.86 .05 85);--primary-foreground: oklch(.14 .01 80);--secondary: oklch(.24 .01 80);--secondary-foreground: oklch(.86 .05 85);--muted: oklch(.24 .01 80);--muted-foreground: oklch(.6 .01 85);--accent: oklch(.24 .01 80);--accent-foreground: oklch(.86 .05 85);--destructive: oklch(.48 .15 25);--destructive-foreground: oklch(.93 .01 85);--border: oklch(.28 .01 80);--input: oklch(.28 .01 80);--ring: oklch(.86 .05 85 / .3);--sidebar: oklch(.17 .01 80);--sidebar-foreground: oklch(.93 .01 85);--sidebar-primary: oklch(.86 .05 85);--sidebar-primary-foreground: oklch(.14 .01 80);--sidebar-accent: oklch(.23 .01 80);--sidebar-accent-foreground: oklch(.93 .01 85);--sidebar-border: oklch(.28 .01 80);--banner-info: oklch(.22 .04 230);--banner-info-foreground: oklch(.88 .05 230);--banner-info-border: oklch(.48 .16 235);--banner-note: oklch(.22 .04 155);--banner-note-foreground: oklch(.88 .06 155);--banner-note-border: oklch(.44 .1 155);--banner-warning: oklch(.26 .06 70);--banner-warning-foreground: oklch(.92 .1 80);--banner-warning-border: oklch(.65 .2 75);--banner-alert: oklch(.23 .05 25);--banner-alert-foreground: oklch(.9 .06 25);--banner-alert-border: oklch(.44 .14 25);--badge-success: oklch(.44 .12 150);--badge-success-foreground: oklch(.93 .01 85);--checkbox-checked: oklch(.86 .05 85);--checkbox-checked-foreground: oklch(.14 .01 80);--checkbox-unchecked-bg: oklch(.22 .01 80);--checkbox-unchecked-border: oklch(.35 .01 80)}:root{--background: oklch(.95 .005 250);--foreground: oklch(.2 .02 250);--card: oklch(.98 .005 250 / .85);--card-foreground: oklch(.2 .02 250);--popover: oklch(1 0 0);--popover-foreground: oklch(.2 .02 250);--primary: oklch(.3 .05 250);--primary-foreground: oklch(.98 .005 250);--secondary: oklch(.97 .005 250);--secondary-foreground: oklch(.3 .05 250);--muted: oklch(.93 .005 250);--muted-foreground: oklch(.5 .02 250);--accent: oklch(.91 .008 250);--accent-foreground: oklch(.3 .05 250);--destructive: oklch(.55 .15 25);--destructive-foreground: oklch(1 0 0);--border: oklch(.88 .005 250);--input: oklch(.88 .005 250);--ring: oklch(.3 .05 250 / .15);--radius: .25rem;--sidebar: oklch(.97 .005 250);--sidebar-foreground: oklch(.25 .02 250);--sidebar-primary: oklch(.3 .05 250);--sidebar-primary-foreground: oklch(.98 .005 250);--sidebar-accent: oklch(.93 .008 250);--sidebar-accent-foreground: oklch(.25 .02 250);--sidebar-border: oklch(.9 .005 250);--banner-info: oklch(.94 .02 245);--banner-info-foreground: oklch(.24 .09 245);--banner-info-border: oklch(.52 .18 245);--banner-note: oklch(.94 .02 162);--banner-note-foreground: oklch(.24 .1 162);--banner-note-border: oklch(.48 .16 162);--banner-warning: oklch(.95 .04 78);--banner-warning-foreground: oklch(.34 .13 62);--banner-warning-border: oklch(.62 .18 72);--banner-alert: oklch(.95 .03 22);--banner-alert-foreground: oklch(.34 .14 22);--banner-alert-border: oklch(.52 .2 22);--badge-success: oklch(.35 .1 160);--badge-success-foreground: oklch(.98 .01 160);--checkbox-checked: oklch(.3 .05 250);--checkbox-checked-foreground: oklch(1 0 0);--checkbox-unchecked-bg: oklch(1 0 0);--checkbox-unchecked-border: oklch(.85 .01 250)}[data-theme=steel]{--background: oklch(.95 .005 250);--foreground: oklch(.2 .02 250);--card: oklch(.98 .005 250 / .85);--card-foreground: oklch(.2 .02 250);--popover: oklch(1 0 0);--popover-foreground: oklch(.2 .02 250);--primary: oklch(.3 .05 250);--primary-foreground: oklch(.98 .005 250);--secondary: oklch(.97 .005 250);--secondary-foreground: oklch(.3 .05 250);--muted: oklch(.93 .005 250);--muted-foreground: oklch(.5 .02 250);--accent: oklch(.91 .008 250);--accent-foreground: oklch(.3 .05 250);--destructive: oklch(.55 .15 25);--destructive-foreground: oklch(1 0 0);--border: oklch(.88 .005 250);--input: oklch(.88 .005 250);--ring: oklch(.3 .05 250 / .15);--radius: .25rem;--sidebar: oklch(.97 .005 250);--sidebar-foreground: oklch(.25 .02 250);--sidebar-primary: oklch(.3 .05 250);--sidebar-primary-foreground: oklch(.98 .005 250);--sidebar-accent: oklch(.93 .008 250);--sidebar-accent-foreground: oklch(.25 .02 250);--sidebar-border: oklch(.9 .005 250);--banner-info: oklch(.94 .02 245);--banner-info-foreground: oklch(.24 .09 245);--banner-info-border: oklch(.52 .18 245);--banner-note: oklch(.94 .02 162);--banner-note-foreground: oklch(.24 .1 162);--banner-note-border: oklch(.48 .16 162);--banner-warning: oklch(.95 .04 78);--banner-warning-foreground: oklch(.34 .13 62);--banner-warning-border: oklch(.62 .18 72);--banner-alert: oklch(.95 .03 22);--banner-alert-foreground: oklch(.34 .14 22);--banner-alert-border: oklch(.52 .2 22);--badge-success: oklch(.35 .1 160);--badge-success-foreground: oklch(.98 .01 160);--checkbox-checked: oklch(.3 .05 250);--checkbox-checked-foreground: oklch(1 0 0);--checkbox-unchecked-bg: oklch(1 0 0);--checkbox-unchecked-border: oklch(.85 .01 250)}.dark,[data-theme=steel].dark{--background: oklch(.18 .015 260);--foreground: oklch(.985 0 0);--card: oklch(.23 .02 260 / .75);--card-foreground: oklch(.985 0 0);--popover: oklch(.21 .015 260);--popover-foreground: oklch(.985 0 0);--primary: oklch(.9 .1 220);--primary-foreground: oklch(.18 .015 260);--secondary: oklch(.28 .02 260);--secondary-foreground: oklch(.9 .1 220);--muted: oklch(.28 .02 260);--muted-foreground: oklch(.705 .015 260);--accent: oklch(.28 .02 260);--accent-foreground: oklch(.9 .1 220);--destructive: oklch(.45 .15 25);--destructive-foreground: oklch(.985 0 0);--border: oklch(.32 .02 260);--input: oklch(.32 .02 260);--ring: oklch(.9 .1 220 / .3);--sidebar: oklch(.21 .015 260);--sidebar-foreground: oklch(.985 0 0);--sidebar-primary: oklch(.9 .1 220);--sidebar-primary-foreground: oklch(.18 .015 260);--sidebar-accent: oklch(.28 .02 260);--sidebar-accent-foreground: oklch(.985 0 0);--sidebar-border: oklch(.32 .02 260);--banner-info: oklch(.274 .079 260);--banner-info-foreground: oklch(.925 .033 260);--banner-info-border: oklch(.488 .2 260);--banner-note: oklch(.266 .065 152);--banner-note-foreground: oklch(.962 .044 156);--banner-note-border: oklch(.45 .1 152);--banner-warning: oklch(.55 .22 100);--banner-warning-foreground: oklch(.99 .15 102);--banner-warning-border: oklch(.75 .25 100);--banner-alert: oklch(.293 .084 27);--banner-alert-foreground: oklch(.969 .071 27);--banner-alert-border: oklch(.45 .12 27);--badge-success: oklch(.48 .15 150);--badge-success-foreground: oklch(1 0 0);--checkbox-checked: oklch(.9 .1 220);--checkbox-checked-foreground: oklch(.18 .015 260);--checkbox-unchecked-bg: oklch(.25 .01 260);--checkbox-unchecked-border: oklch(.4 .01 260)}
@@ -0,0 +1,25 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import "react";
3
+ import { c as s } from "./utils.js";
4
+ function l({
5
+ className: e,
6
+ ...o
7
+ }) {
8
+ return /* @__PURE__ */ r(
9
+ "select",
10
+ {
11
+ "data-slot": "select",
12
+ className: s(
13
+ "flex h-9 w-full rounded border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors outline-none",
14
+ "focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:border-ring",
15
+ "disabled:pointer-events-none disabled:opacity-50",
16
+ e
17
+ ),
18
+ ...o
19
+ }
20
+ );
21
+ }
22
+ export {
23
+ l as S
24
+ };
25
+ //# sourceMappingURL=Select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Select.js","sources":["../../src/components/Select/Select.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport { cn } from '@/utils'\n\n/** Native select styled to match design-system Input (form control). */\nexport function Select({\n\tclassName,\n\t...props\n}: React.ComponentProps<'select'>) {\n\treturn (\n\t\t<select\n\t\t\tdata-slot=\"select\"\n\t\t\tclassName={cn(\n\t\t\t\t'flex h-9 w-full rounded border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors outline-none',\n\t\t\t\t'focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:border-ring',\n\t\t\t\t'disabled:pointer-events-none disabled:opacity-50',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n"],"names":["Select","className","props","jsx","cn"],"mappings":";;;AAKO,SAASA,EAAO;AAAA,EACtB,WAAAC;AAAA,EACA,GAAGC;AACJ,GAAmC;AAClC,SACC,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,aAAU;AAAA,MACV,WAAWC;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACAH;AAAA,MAAA;AAAA,MAEA,GAAGC;AAAA,IAAA;AAAA,EAAA;AAGP;"}
@@ -0,0 +1,12 @@
1
+ import { createContext as t, useContext as o } from "react";
2
+ const r = t(null);
3
+ function s() {
4
+ const e = o(r);
5
+ if (!e) throw new Error("useTheme must be used within ThemeProvider");
6
+ return e;
7
+ }
8
+ export {
9
+ r as T,
10
+ s as u
11
+ };
12
+ //# sourceMappingURL=useTheme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTheme.js","sources":["../../src/themes/ThemeContext.ts","../../src/themes/useTheme.ts"],"sourcesContent":["import { createContext } from 'react'\nimport type { ColorTheme, Theme } from './ThemeProvider'\n\nexport interface ThemeContextValue {\n\ttheme: Theme\n\tsetTheme: (theme: Theme) => void\n\teffectiveTheme: 'light' | 'dark'\n\tcolorTheme: ColorTheme\n\tsetColorTheme: (colorTheme: ColorTheme) => void\n}\n\nexport const ThemeContext = createContext<ThemeContextValue | null>(null)\n","import { useContext } from 'react'\nimport { ThemeContext } from './ThemeContext'\n\nexport function useTheme() {\n\tconst ctx = useContext(ThemeContext)\n\tif (!ctx) throw new Error('useTheme must be used within ThemeProvider')\n\treturn ctx\n}\n"],"names":["ThemeContext","createContext","useTheme","ctx","useContext"],"mappings":";AAWO,MAAMA,IAAeC,EAAwC,IAAI;ACRjE,SAASC,IAAW;AAC1B,QAAMC,IAAMC,EAAWJ,CAAY;AACnC,MAAI,CAACG,EAAK,OAAM,IAAI,MAAM,4CAA4C;AACtE,SAAOA;AACR;"}
@@ -0,0 +1,10 @@
1
+ import type { ColorTheme, Theme } from './ThemeProvider';
2
+ export interface ThemeContextValue {
3
+ theme: Theme;
4
+ setTheme: (theme: Theme) => void;
5
+ effectiveTheme: 'light' | 'dark';
6
+ colorTheme: ColorTheme;
7
+ setColorTheme: (colorTheme: ColorTheme) => void;
8
+ }
9
+ export declare const ThemeContext: import("react").Context<ThemeContextValue | null>;
10
+ //# sourceMappingURL=ThemeContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeContext.d.ts","sourceRoot":"","sources":["../../src/themes/ThemeContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAExD,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,KAAK,CAAA;IACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,cAAc,EAAE,OAAO,GAAG,MAAM,CAAA;IAChC,UAAU,EAAE,UAAU,CAAA;IACtB,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAA;CAC/C;AAED,eAAO,MAAM,YAAY,mDAAgD,CAAA"}
@@ -0,0 +1,9 @@
1
+ import type { ReactNode } from 'react';
2
+ import './linen.css';
3
+ import './steel.css';
4
+ export type Theme = 'light' | 'dark' | 'system';
5
+ export type ColorTheme = 'linen' | 'steel';
6
+ export declare function ThemeProvider({ children }: {
7
+ children: ReactNode;
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=ThemeProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/themes/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,aAAa,CAAA;AACpB,OAAO,aAAa,CAAA;AAEpB,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;AAC/C,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,CAAA;AAiC1C,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CA6ClE"}
@@ -0,0 +1,3 @@
1
+ export { ThemeProvider, type Theme, type ColorTheme } from './ThemeProvider';
2
+ export { useTheme } from './useTheme';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/themes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/themes/theme.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare function useTheme(): import("./ThemeContext").ThemeContextValue;
2
+ //# sourceMappingURL=useTheme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../src/themes/useTheme.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,+CAIvB"}
package/dist/themes.js ADDED
@@ -0,0 +1,50 @@
1
+ import { jsx as S } from "react/jsx-runtime";
2
+ import { useState as s, useEffect as m, useCallback as d, useMemo as k } from "react";
3
+ import { T as E } from "./shared/useTheme.js";
4
+ import { u as R } from "./shared/useTheme.js";
5
+ const l = "theme", h = "color-theme";
6
+ function y() {
7
+ if (typeof window > "u") return "system";
8
+ const e = localStorage.getItem(l);
9
+ return e === "light" || e === "dark" || e === "system" ? e : "dark";
10
+ }
11
+ function v() {
12
+ if (typeof window > "u") return "linen";
13
+ const e = localStorage.getItem(h);
14
+ return e === "linen" || e === "steel" ? e : "linen";
15
+ }
16
+ function w(e) {
17
+ const t = document.documentElement;
18
+ e === "dark" ? t.classList.add("dark") : t.classList.remove("dark");
19
+ }
20
+ function C(e) {
21
+ document.documentElement.setAttribute("data-theme", e);
22
+ }
23
+ function O({ children: e }) {
24
+ const [t, u] = s(y), [r, f] = s(v), [T, p] = s(
25
+ () => window.matchMedia("(prefers-color-scheme: dark)").matches
26
+ ), n = t === "system" ? T ? "dark" : "light" : t;
27
+ m(() => {
28
+ w(n);
29
+ }, [n]), m(() => {
30
+ C(r);
31
+ }, [r]), m(() => {
32
+ if (t !== "system") return;
33
+ const o = window.matchMedia("(prefers-color-scheme: dark)"), i = () => p(o.matches);
34
+ return o.addEventListener("change", i), () => o.removeEventListener("change", i);
35
+ }, [t]);
36
+ const a = d((o) => {
37
+ u(o), localStorage.setItem(l, o);
38
+ }, []), c = d((o) => {
39
+ f(o), localStorage.setItem(h, o);
40
+ }, []), g = k(
41
+ () => ({ theme: t, setTheme: a, effectiveTheme: n, colorTheme: r, setColorTheme: c }),
42
+ [t, a, n, r, c]
43
+ );
44
+ return /* @__PURE__ */ S(E.Provider, { value: g, children: e });
45
+ }
46
+ export {
47
+ O as ThemeProvider,
48
+ R as useTheme
49
+ };
50
+ //# sourceMappingURL=themes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.js","sources":["../src/themes/ThemeProvider.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { ThemeContext } from './ThemeContext'\nimport './linen.css'\nimport './steel.css'\n\nexport type Theme = 'light' | 'dark' | 'system'\nexport type ColorTheme = 'linen' | 'steel'\n\nconst STORAGE_KEY = 'theme'\nconst COLOR_THEME_STORAGE_KEY = 'color-theme'\n\nfunction getStoredTheme(): Theme {\n\tif (typeof window === 'undefined') return 'system'\n\tconst stored = localStorage.getItem(STORAGE_KEY)\n\tif (stored === 'light' || stored === 'dark' || stored === 'system')\n\t\treturn stored\n\treturn 'dark'\n}\n\nfunction getStoredColorTheme(): ColorTheme {\n\tif (typeof window === 'undefined') return 'linen'\n\tconst stored = localStorage.getItem(COLOR_THEME_STORAGE_KEY)\n\tif (stored === 'linen' || stored === 'steel') return stored\n\treturn 'linen'\n}\n\nfunction applyTheme(effective: 'light' | 'dark') {\n\tconst root = document.documentElement\n\tif (effective === 'dark') {\n\t\troot.classList.add('dark')\n\t} else {\n\t\troot.classList.remove('dark')\n\t}\n}\n\nfunction applyColorTheme(colorTheme: ColorTheme) {\n\tdocument.documentElement.setAttribute('data-theme', colorTheme)\n}\n\nexport function ThemeProvider({ children }: { children: ReactNode }) {\n\tconst [theme, setThemeState] = useState<Theme>(getStoredTheme)\n\tconst [colorTheme, setColorThemeState] =\n\t\tuseState<ColorTheme>(getStoredColorTheme)\n\tconst [systemDark, setSystemDark] = useState(\n\t\t() => window.matchMedia('(prefers-color-scheme: dark)').matches,\n\t)\n\n\tconst effectiveTheme: 'light' | 'dark' =\n\t\ttheme === 'system' ? (systemDark ? 'dark' : 'light') : theme\n\n\tuseEffect(() => {\n\t\tapplyTheme(effectiveTheme)\n\t}, [effectiveTheme])\n\n\tuseEffect(() => {\n\t\tapplyColorTheme(colorTheme)\n\t}, [colorTheme])\n\n\tuseEffect(() => {\n\t\tif (theme !== 'system') return\n\t\tconst media = window.matchMedia('(prefers-color-scheme: dark)')\n\t\tconst handler = () => setSystemDark(media.matches)\n\t\tmedia.addEventListener('change', handler)\n\t\treturn () => media.removeEventListener('change', handler)\n\t}, [theme])\n\n\tconst setTheme = useCallback((next: Theme) => {\n\t\tsetThemeState(next)\n\t\tlocalStorage.setItem(STORAGE_KEY, next)\n\t}, [])\n\n\tconst setColorTheme = useCallback((next: ColorTheme) => {\n\t\tsetColorThemeState(next)\n\t\tlocalStorage.setItem(COLOR_THEME_STORAGE_KEY, next)\n\t}, [])\n\n\tconst value = useMemo(\n\t\t() => ({ theme, setTheme, effectiveTheme, colorTheme, setColorTheme }),\n\t\t[theme, setTheme, effectiveTheme, colorTheme, setColorTheme],\n\t)\n\n\treturn (\n\t\t<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>\n\t)\n}\n"],"names":["STORAGE_KEY","COLOR_THEME_STORAGE_KEY","getStoredTheme","stored","getStoredColorTheme","applyTheme","effective","root","applyColorTheme","colorTheme","ThemeProvider","children","theme","setThemeState","useState","setColorThemeState","systemDark","setSystemDark","effectiveTheme","useEffect","media","handler","setTheme","useCallback","next","setColorTheme","value","useMemo","jsx","ThemeContext"],"mappings":";;;;AASA,MAAMA,IAAc,SACdC,IAA0B;AAEhC,SAASC,IAAwB;AAChC,MAAI,OAAO,SAAW,IAAa,QAAO;AAC1C,QAAMC,IAAS,aAAa,QAAQH,CAAW;AAC/C,SAAIG,MAAW,WAAWA,MAAW,UAAUA,MAAW,WAClDA,IACD;AACR;AAEA,SAASC,IAAkC;AAC1C,MAAI,OAAO,SAAW,IAAa,QAAO;AAC1C,QAAMD,IAAS,aAAa,QAAQF,CAAuB;AAC3D,SAAIE,MAAW,WAAWA,MAAW,UAAgBA,IAC9C;AACR;AAEA,SAASE,EAAWC,GAA6B;AAChD,QAAMC,IAAO,SAAS;AACtB,EAAID,MAAc,SACjBC,EAAK,UAAU,IAAI,MAAM,IAEzBA,EAAK,UAAU,OAAO,MAAM;AAE9B;AAEA,SAASC,EAAgBC,GAAwB;AAChD,WAAS,gBAAgB,aAAa,cAAcA,CAAU;AAC/D;AAEO,SAASC,EAAc,EAAE,UAAAC,KAAqC;AACpE,QAAM,CAACC,GAAOC,CAAa,IAAIC,EAAgBZ,CAAc,GACvD,CAACO,GAAYM,CAAkB,IACpCD,EAAqBV,CAAmB,GACnC,CAACY,GAAYC,CAAa,IAAIH;AAAA,IACnC,MAAM,OAAO,WAAW,8BAA8B,EAAE;AAAA,EAAA,GAGnDI,IACLN,MAAU,WAAYI,IAAa,SAAS,UAAWJ;AAExD,EAAAO,EAAU,MAAM;AACf,IAAAd,EAAWa,CAAc;AAAA,EAC1B,GAAG,CAACA,CAAc,CAAC,GAEnBC,EAAU,MAAM;AACf,IAAAX,EAAgBC,CAAU;AAAA,EAC3B,GAAG,CAACA,CAAU,CAAC,GAEfU,EAAU,MAAM;AACf,QAAIP,MAAU,SAAU;AACxB,UAAMQ,IAAQ,OAAO,WAAW,8BAA8B,GACxDC,IAAU,MAAMJ,EAAcG,EAAM,OAAO;AACjD,WAAAA,EAAM,iBAAiB,UAAUC,CAAO,GACjC,MAAMD,EAAM,oBAAoB,UAAUC,CAAO;AAAA,EACzD,GAAG,CAACT,CAAK,CAAC;AAEV,QAAMU,IAAWC,EAAY,CAACC,MAAgB;AAC7C,IAAAX,EAAcW,CAAI,GAClB,aAAa,QAAQxB,GAAawB,CAAI;AAAA,EACvC,GAAG,CAAA,CAAE,GAECC,IAAgBF,EAAY,CAACC,MAAqB;AACvD,IAAAT,EAAmBS,CAAI,GACvB,aAAa,QAAQvB,GAAyBuB,CAAI;AAAA,EACnD,GAAG,CAAA,CAAE,GAECE,IAAQC;AAAA,IACb,OAAO,EAAE,OAAAf,GAAO,UAAAU,GAAU,gBAAAJ,GAAgB,YAAAT,GAAY,eAAAgB,EAAA;AAAA,IACtD,CAACb,GAAOU,GAAUJ,GAAgBT,GAAYgB,CAAa;AAAA,EAAA;AAG5D,SACC,gBAAAG,EAACC,EAAa,UAAb,EAAsB,OAAAH,GAAe,UAAAf,EAAA,CAAS;AAEjD;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abumble/design-system",
3
- "version": "0.0.38",
3
+ "version": "0.0.39",
4
4
  "files": [
5
5
  "dist",
6
6
  "src/styles.css",
@@ -11,141 +11,9 @@
11
11
  "import": "./dist/index.js",
12
12
  "types": "./dist/index.d.ts"
13
13
  },
14
- "./components/Banner": {
15
- "import": "./dist/components/Banner.js",
16
- "types": "./dist/components/Banner/Banner.d.ts"
17
- },
18
- "./components/Breadcrumb": {
19
- "import": "./dist/components/Breadcrumb.js",
20
- "types": "./dist/components/Breadcrumb/Breadcrumb.d.ts"
21
- },
22
- "./components/Button": {
23
- "import": "./dist/components/Button.js",
24
- "types": "./dist/components/Button/Button.d.ts"
25
- },
26
- "./components/Card": {
27
- "import": "./dist/components/Card.js",
28
- "types": "./dist/components/Card/Card.d.ts"
29
- },
30
- "./components/Carousel": {
31
- "import": "./dist/components/Carousel.js",
32
- "types": "./dist/components/Carousel/Carousel.d.ts"
33
- },
34
- "./components/CodeDisplay": {
35
- "import": "./dist/components/CodeDisplay.js",
36
- "types": "./dist/components/CodeDisplay/CodeDisplay.d.ts"
37
- },
38
- "./components/Collapsible": {
39
- "import": "./dist/components/Collapsible.js",
40
- "types": "./dist/components/Collapsible/Collapsible.d.ts"
41
- },
42
- "./components/ContextMenu": {
43
- "import": "./dist/components/ContextMenu.js",
44
- "types": "./dist/components/ContextMenu/ContextMenu.d.ts"
45
- },
46
- "./components/Empty": {
47
- "import": "./dist/components/Empty.js",
48
- "types": "./dist/components/Empty/Empty.d.ts"
49
- },
50
- "./components/Input": {
51
- "import": "./dist/components/Input.js",
52
- "types": "./dist/components/Input/Input.d.ts"
53
- },
54
- "./components/List": {
55
- "import": "./dist/components/List.js",
56
- "types": "./dist/components/List/List.d.ts"
57
- },
58
- "./components/NotFound": {
59
- "import": "./dist/components/NotFound.js",
60
- "types": "./dist/components/NotFound/NotFound.d.ts"
61
- },
62
- "./components/Popover": {
63
- "import": "./dist/components/Popover.js",
64
- "types": "./dist/components/Popover/Popover.d.ts"
65
- },
66
- "./components/Separator": {
67
- "import": "./dist/components/Separator.js",
68
- "types": "./dist/components/Separator/Separator.d.ts"
69
- },
70
- "./components/Sheet": {
71
- "import": "./dist/components/Sheet.js",
72
- "types": "./dist/components/Sheet/Sheet.d.ts"
73
- },
74
- "./components/Sidebar": {
75
- "import": "./dist/components/Sidebar.js",
76
- "types": "./dist/components/Sidebar/Sidebar.d.ts"
77
- },
78
- "./components/Skeleton": {
79
- "import": "./dist/components/Skeleton.js",
80
- "types": "./dist/components/Skeleton/Skeleton.d.ts"
81
- },
82
- "./components/Tooltip": {
83
- "import": "./dist/components/Tooltip.js",
84
- "types": "./dist/components/Tooltip/Tooltip.d.ts"
85
- },
86
- "./components/UnderConstruction": {
87
- "import": "./dist/components/UnderConstruction.js",
88
- "types": "./dist/components/UnderConstruction/UnderConstruction.d.ts"
89
- },
90
- "./components/Badge": {
91
- "import": "./dist/components/Badge.js",
92
- "types": "./dist/components/Badge/Badge.d.ts"
93
- },
94
- "./components/Label": {
95
- "import": "./dist/components/Label.js",
96
- "types": "./dist/components/Label/Label.d.ts"
97
- },
98
- "./components/Checkbox": {
99
- "import": "./dist/components/Checkbox.js",
100
- "types": "./dist/components/Checkbox/Checkbox.d.ts"
101
- },
102
- "./components/Select": {
103
- "import": "./dist/components/Select.js",
104
- "types": "./dist/components/Select/Select.d.ts"
105
- },
106
- "./components/Textarea": {
107
- "import": "./dist/components/Textarea.js",
108
- "types": "./dist/components/Textarea/Textarea.d.ts"
109
- },
110
- "./components/Table": {
111
- "import": "./dist/components/Table.js",
112
- "types": "./dist/components/Table/Table.d.ts"
113
- },
114
- "./components/PageHeader": {
115
- "import": "./dist/components/PageHeader.js",
116
- "types": "./dist/components/PageHeader/PageHeader.d.ts"
117
- },
118
- "./components/Dialog": {
119
- "import": "./dist/components/Dialog.js",
120
- "types": "./dist/components/Dialog/Dialog.d.ts"
121
- },
122
- "./components/FieldsTable": {
123
- "import": "./dist/components/FieldsTable.js",
124
- "types": "./dist/components/FieldsTable/FieldsTable.d.ts"
125
- },
126
- "./components/ConfirmDeleteDialog": {
127
- "import": "./dist/components/ConfirmDeleteDialog.js",
128
- "types": "./dist/components/ConfirmDeleteDialog/ConfirmDeleteDialog.d.ts"
129
- },
130
- "./components/ActionsPopover": {
131
- "import": "./dist/components/ActionsPopover.js",
132
- "types": "./dist/components/ActionsPopover/ActionsPopover.d.ts"
133
- },
134
- "./components/BackLink": {
135
- "import": "./dist/components/BackLink.js",
136
- "types": "./dist/components/BackLink/BackLink.d.ts"
137
- },
138
- "./components/BannerHeader": {
139
- "import": "./dist/components/BannerHeader.js",
140
- "types": "./dist/components/BannerHeader/BannerHeader.d.ts"
141
- },
142
- "./components/DelayedLoadingFallback": {
143
- "import": "./dist/components/DelayedLoadingFallback.js",
144
- "types": "./dist/components/DelayedLoadingFallback/DelayedLoadingFallback.d.ts"
145
- },
146
- "./components/Toaster": {
147
- "import": "./dist/components/Toaster.js",
148
- "types": "./dist/components/Toaster/Toaster.d.ts"
14
+ "./components/*": {
15
+ "import": "./dist/components/*.js",
16
+ "types": "./dist/components/*/index.d.ts"
149
17
  },
150
18
  "./hooks/use-delayed-loading": {
151
19
  "import": "./dist/use-delayed-loading.js",
@@ -168,6 +36,10 @@
168
36
  "types": "./dist/hooks/use-mobile.d.ts"
169
37
  },
170
38
  "./styles.css": "./src/styles.css",
39
+ "./themes": {
40
+ "import": "./dist/themes.js",
41
+ "types": "./dist/themes/index.d.ts"
42
+ },
171
43
  "./themes/linen.css": "./src/themes/linen.css",
172
44
  "./themes/steel.css": "./src/themes/steel.css"
173
45
  },
@@ -0,0 +1,12 @@
1
+ import { createContext } from 'react'
2
+ import type { ColorTheme, Theme } from './ThemeProvider'
3
+
4
+ export interface ThemeContextValue {
5
+ theme: Theme
6
+ setTheme: (theme: Theme) => void
7
+ effectiveTheme: 'light' | 'dark'
8
+ colorTheme: ColorTheme
9
+ setColorTheme: (colorTheme: ColorTheme) => void
10
+ }
11
+
12
+ export const ThemeContext = createContext<ThemeContextValue | null>(null)
@@ -0,0 +1,86 @@
1
+ import type { ReactNode } from 'react'
2
+ import { useCallback, useEffect, useMemo, useState } from 'react'
3
+ import { ThemeContext } from './ThemeContext'
4
+ import './linen.css'
5
+ import './steel.css'
6
+
7
+ export type Theme = 'light' | 'dark' | 'system'
8
+ export type ColorTheme = 'linen' | 'steel'
9
+
10
+ const STORAGE_KEY = 'theme'
11
+ const COLOR_THEME_STORAGE_KEY = 'color-theme'
12
+
13
+ function getStoredTheme(): Theme {
14
+ if (typeof window === 'undefined') return 'system'
15
+ const stored = localStorage.getItem(STORAGE_KEY)
16
+ if (stored === 'light' || stored === 'dark' || stored === 'system')
17
+ return stored
18
+ return 'dark'
19
+ }
20
+
21
+ function getStoredColorTheme(): ColorTheme {
22
+ if (typeof window === 'undefined') return 'linen'
23
+ const stored = localStorage.getItem(COLOR_THEME_STORAGE_KEY)
24
+ if (stored === 'linen' || stored === 'steel') return stored
25
+ return 'linen'
26
+ }
27
+
28
+ function applyTheme(effective: 'light' | 'dark') {
29
+ const root = document.documentElement
30
+ if (effective === 'dark') {
31
+ root.classList.add('dark')
32
+ } else {
33
+ root.classList.remove('dark')
34
+ }
35
+ }
36
+
37
+ function applyColorTheme(colorTheme: ColorTheme) {
38
+ document.documentElement.setAttribute('data-theme', colorTheme)
39
+ }
40
+
41
+ export function ThemeProvider({ children }: { children: ReactNode }) {
42
+ const [theme, setThemeState] = useState<Theme>(getStoredTheme)
43
+ const [colorTheme, setColorThemeState] =
44
+ useState<ColorTheme>(getStoredColorTheme)
45
+ const [systemDark, setSystemDark] = useState(
46
+ () => window.matchMedia('(prefers-color-scheme: dark)').matches,
47
+ )
48
+
49
+ const effectiveTheme: 'light' | 'dark' =
50
+ theme === 'system' ? (systemDark ? 'dark' : 'light') : theme
51
+
52
+ useEffect(() => {
53
+ applyTheme(effectiveTheme)
54
+ }, [effectiveTheme])
55
+
56
+ useEffect(() => {
57
+ applyColorTheme(colorTheme)
58
+ }, [colorTheme])
59
+
60
+ useEffect(() => {
61
+ if (theme !== 'system') return
62
+ const media = window.matchMedia('(prefers-color-scheme: dark)')
63
+ const handler = () => setSystemDark(media.matches)
64
+ media.addEventListener('change', handler)
65
+ return () => media.removeEventListener('change', handler)
66
+ }, [theme])
67
+
68
+ const setTheme = useCallback((next: Theme) => {
69
+ setThemeState(next)
70
+ localStorage.setItem(STORAGE_KEY, next)
71
+ }, [])
72
+
73
+ const setColorTheme = useCallback((next: ColorTheme) => {
74
+ setColorThemeState(next)
75
+ localStorage.setItem(COLOR_THEME_STORAGE_KEY, next)
76
+ }, [])
77
+
78
+ const value = useMemo(
79
+ () => ({ theme, setTheme, effectiveTheme, colorTheme, setColorTheme }),
80
+ [theme, setTheme, effectiveTheme, colorTheme, setColorTheme],
81
+ )
82
+
83
+ return (
84
+ <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
85
+ )
86
+ }
@@ -0,0 +1,2 @@
1
+ export { ThemeProvider, type Theme, type ColorTheme } from './ThemeProvider'
2
+ export { useTheme } from './useTheme'
@@ -0,0 +1,3 @@
1
+ // This file has been reorganized.
2
+ // ThemeProvider, useTheme, Theme → ./ThemeProvider (exported via @abumble/design-system/themes)
3
+ // ThemeToggle → src/components/ThemeToggle (exported via @abumble/design-system/components/ThemeToggle)
@@ -0,0 +1,8 @@
1
+ import { useContext } from 'react'
2
+ import { ThemeContext } from './ThemeContext'
3
+
4
+ export function useTheme() {
5
+ const ctx = useContext(ThemeContext)
6
+ if (!ctx) throw new Error('useTheme must be used within ThemeProvider')
7
+ return ctx
8
+ }