@cosxai/ui 0.25.0 → 1.0.0-alpha.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.
Files changed (165) hide show
  1. package/CHANGELOG.md +597 -0
  2. package/NOTICE +11 -0
  3. package/README.md +52 -0
  4. package/package.json +57 -7
  5. package/src/brand.css +13 -0
  6. package/src/components/Badge.tsx +68 -0
  7. package/src/components/Button.tsx +178 -0
  8. package/src/components/Card.tsx +42 -0
  9. package/src/components/Checkbox.tsx +67 -0
  10. package/src/components/Dialog.tsx +111 -0
  11. package/src/components/Field.tsx +66 -0
  12. package/src/components/Figure.tsx +30 -0
  13. package/src/components/Icon.tsx +32 -0
  14. package/src/components/IconButton.tsx +55 -0
  15. package/src/components/Input.tsx +74 -0
  16. package/src/components/Logo.tsx +62 -0
  17. package/src/components/Marker.tsx +26 -0
  18. package/src/components/MetaLabel.tsx +38 -0
  19. package/src/components/Radio.tsx +72 -0
  20. package/src/components/Select.tsx +351 -0
  21. package/src/components/Spinner.tsx +20 -0
  22. package/src/components/Switch.tsx +67 -0
  23. package/src/components/Table.tsx +196 -0
  24. package/src/components/Tabs.tsx +124 -0
  25. package/src/components/Tag.tsx +35 -0
  26. package/src/components/Textarea.tsx +46 -0
  27. package/src/components/ThemeProvider.tsx +80 -0
  28. package/src/components/Toast.tsx +159 -0
  29. package/src/components/Tooltip.tsx +57 -0
  30. package/src/components/core.test.tsx +242 -0
  31. package/src/components/forms-control.ts +36 -0
  32. package/src/components/forms.test.tsx +280 -0
  33. package/src/components/logo-art.ts +4 -0
  34. package/src/components/overlays.test.tsx +245 -0
  35. package/src/components/useButtonAction.ts +57 -0
  36. package/src/fonts.css +20 -0
  37. package/src/index.ts +34 -24
  38. package/src/lib/cn.ts +23 -6
  39. package/src/modes.css +10 -0
  40. package/src/styles.css +19 -0
  41. package/src/theme.css +143 -0
  42. package/src/tokens/colors.css +112 -0
  43. package/src/tokens/compat.css +36 -0
  44. package/src/tokens/elevation.css +14 -0
  45. package/src/tokens/motion.css +42 -0
  46. package/src/tokens/spacing.css +55 -0
  47. package/src/tokens/typography-cjk.css +42 -0
  48. package/src/tokens/typography.css +81 -0
  49. package/src/actionbar/ActionBar.tsx +0 -837
  50. package/src/actionbar/ActionBarButton.tsx +0 -111
  51. package/src/actionbar/ActionBarMenuGroup.tsx +0 -116
  52. package/src/actionbar/ActionBarModeHandle.tsx +0 -171
  53. package/src/actionbar/ActionBarProvider.tsx +0 -91
  54. package/src/actionbar/actionbar-context.ts +0 -45
  55. package/src/actionbar/index.ts +0 -28
  56. package/src/actionbar/types.ts +0 -147
  57. package/src/actionbar/useActionBarItems.ts +0 -60
  58. package/src/actionbar/useActionBarMode.ts +0 -144
  59. package/src/actionbar/useActionBarPanel.ts +0 -56
  60. package/src/actionbar/useActionBarStatusDot.ts +0 -49
  61. package/src/actionbar/useActionBarToast.ts +0 -33
  62. package/src/ambient/AmbientBackdrop.tsx +0 -74
  63. package/src/ambient/CommandInput.tsx +0 -107
  64. package/src/ambient/SuperbarStrip.tsx +0 -36
  65. package/src/ambient/index.ts +0 -6
  66. package/src/bento/BentoCell.tsx +0 -66
  67. package/src/bento/BentoGrid.tsx +0 -42
  68. package/src/bento/index.ts +0 -2
  69. package/src/command/CommandPalette.tsx +0 -329
  70. package/src/command/CommandProvider.tsx +0 -57
  71. package/src/command/command-context.ts +0 -12
  72. package/src/command/index.ts +0 -6
  73. package/src/command/rank.ts +0 -50
  74. package/src/command/types.ts +0 -37
  75. package/src/command/useCommandSource.ts +0 -37
  76. package/src/dialogs/DialogsProvider.tsx +0 -216
  77. package/src/dialogs/Modal.tsx +0 -260
  78. package/src/dialogs/Toast.tsx +0 -85
  79. package/src/dialogs/dialogs-context.ts +0 -6
  80. package/src/dialogs/index.ts +0 -10
  81. package/src/dialogs/types.ts +0 -37
  82. package/src/dialogs/useDialogs.ts +0 -8
  83. package/src/editorial/EditorialSpotlight.tsx +0 -63
  84. package/src/editorial/Folio.tsx +0 -52
  85. package/src/editorial/PlateMarker.tsx +0 -33
  86. package/src/editorial/RomanSection.tsx +0 -65
  87. package/src/editorial/RunningMarginalia.tsx +0 -65
  88. package/src/editorial/index.ts +0 -10
  89. package/src/hooks/index.ts +0 -5
  90. package/src/hooks/useKeyboardHotkey.ts +0 -93
  91. package/src/hooks/useReducedMotion.ts +0 -20
  92. package/src/hooks/useViewport.ts +0 -61
  93. package/src/layout/Breadcrumb.tsx +0 -74
  94. package/src/layout/LeftNavRail.tsx +0 -139
  95. package/src/layout/MobileTabBar.tsx +0 -101
  96. package/src/layout/NavItem.tsx +0 -128
  97. package/src/layout/NavSearchTrigger.tsx +0 -88
  98. package/src/layout/NavSection.tsx +0 -40
  99. package/src/layout/RightSidebarPanel.tsx +0 -111
  100. package/src/layout/Shell.tsx +0 -91
  101. package/src/layout/SidePanel.tsx +0 -316
  102. package/src/layout/StickyBanner.tsx +0 -83
  103. package/src/layout/Topbar.tsx +0 -68
  104. package/src/layout/index.ts +0 -24
  105. package/src/layout/useNavRailState.ts +0 -69
  106. package/src/lib/time-utils.ts +0 -44
  107. package/src/neobrutalism/Marquee.tsx +0 -81
  108. package/src/neobrutalism/Sticker.tsx +0 -71
  109. package/src/neobrutalism/index.ts +0 -4
  110. package/src/primitives/Avatar.tsx +0 -53
  111. package/src/primitives/Button.tsx +0 -67
  112. package/src/primitives/Card.tsx +0 -41
  113. package/src/primitives/Checkbox.tsx +0 -87
  114. package/src/primitives/Chip.tsx +0 -191
  115. package/src/primitives/Combobox.tsx +0 -507
  116. package/src/primitives/CopyField.tsx +0 -139
  117. package/src/primitives/CountBadge.tsx +0 -50
  118. package/src/primitives/Input.tsx +0 -204
  119. package/src/primitives/Kbd.tsx +0 -45
  120. package/src/primitives/MentionCombobox.tsx +0 -612
  121. package/src/primitives/MultiCombobox.tsx +0 -327
  122. package/src/primitives/PageHeader.tsx +0 -77
  123. package/src/primitives/Radio.tsx +0 -131
  124. package/src/primitives/SegmentedControl.tsx +0 -135
  125. package/src/primitives/Select.tsx +0 -779
  126. package/src/primitives/SignaturePad.tsx +0 -461
  127. package/src/primitives/Tag.tsx +0 -56
  128. package/src/primitives/Textarea.tsx +0 -62
  129. package/src/primitives/ToggleSwitch.tsx +0 -79
  130. package/src/primitives/Tooltip.tsx +0 -213
  131. package/src/primitives/index.ts +0 -53
  132. package/src/pwa/InstallPromptBanner.tsx +0 -132
  133. package/src/pwa/index.ts +0 -4
  134. package/src/pwa/manifest.template.json +0 -20
  135. package/src/pwa/registerSW.ts +0 -55
  136. package/src/riso/Halftone.tsx +0 -85
  137. package/src/riso/Misregister.tsx +0 -63
  138. package/src/riso/RisoStamp.tsx +0 -76
  139. package/src/riso/index.ts +0 -3
  140. package/src/sketch/HandUnderline.tsx +0 -53
  141. package/src/sketch/RoughArrow.tsx +0 -91
  142. package/src/sketch/RoughBox.tsx +0 -73
  143. package/src/sketch/StickyNote.tsx +0 -56
  144. package/src/sketch/index.ts +0 -4
  145. package/src/styles/base.css +0 -186
  146. package/src/styles/chrome-ambient.css +0 -235
  147. package/src/styles/chrome-bento.css +0 -192
  148. package/src/styles/chrome-editorial.css +0 -168
  149. package/src/styles/chrome-neobrutalism.css +0 -326
  150. package/src/styles/chrome-riso.css +0 -339
  151. package/src/styles/chrome-sketch.css +0 -362
  152. package/src/styles/chrome-swiss.css +0 -265
  153. package/src/styles/chrome-terminal.css +0 -272
  154. package/src/styles/fonts.css +0 -1034
  155. package/src/styles/index.css +0 -343
  156. package/src/styles/tokens.css +0 -941
  157. package/src/terminal/AsciiBox.tsx +0 -65
  158. package/src/terminal/BrailleSpinner.tsx +0 -46
  159. package/src/terminal/index.ts +0 -4
  160. package/src/theme/ThemeProvider.tsx +0 -99
  161. package/src/theme/index.ts +0 -6
  162. package/src/theme/inline-script.ts +0 -40
  163. package/src/theme/theme-context.ts +0 -7
  164. package/src/theme/types.ts +0 -39
  165. package/src/theme/useTheme.ts +0 -8
@@ -1,65 +0,0 @@
1
- import type { ReactNode, CSSProperties } from "react";
2
-
3
- // Bordered block with an ASCII-style title cut into the top
4
- // border — `╭─ logs ──╮`. Implementation uses a regular CSS
5
- // border + an absolutely-positioned title that masks a slice of
6
- // the border with the page background.
7
- //
8
- // Looks best under terminal chrome but works under any —
9
- // consumers can use it as a "labelled block" anywhere.
10
-
11
- export interface AsciiBoxProps {
12
- // Title text shown cut into the top border.
13
- title?: string;
14
- children: ReactNode;
15
- // px padding inside the body. Default 14.
16
- padding?: number;
17
- // Background colour to use for the title mask. Defaults to
18
- // the surrounding canvas. Override to match a parent surface
19
- // (e.g. when the box sits on a card).
20
- maskBg?: string;
21
- className?: string;
22
- style?: CSSProperties;
23
- }
24
-
25
- export function AsciiBox({
26
- title,
27
- children,
28
- padding = 14,
29
- maskBg = "var(--ck-bg-canvas)",
30
- className,
31
- style,
32
- }: AsciiBoxProps) {
33
- return (
34
- <div
35
- className={className}
36
- style={{
37
- position: "relative",
38
- border: "1px solid var(--ck-border-subtle)",
39
- borderRadius: 2,
40
- padding,
41
- fontFamily: "var(--ck-font-mono)",
42
- ...style,
43
- }}
44
- >
45
- {title && (
46
- <span
47
- aria-hidden
48
- style={{
49
- position: "absolute",
50
- top: -8,
51
- left: 12,
52
- padding: "0 6px",
53
- background: maskBg,
54
- color: "var(--ck-text-secondary)",
55
- font: "500 11px/1 var(--ck-font-mono)",
56
- letterSpacing: 0,
57
- }}
58
- >
59
- ─ {title} ─
60
- </span>
61
- )}
62
- {children}
63
- </div>
64
- );
65
- }
@@ -1,46 +0,0 @@
1
- import { useEffect, useState } from "react";
2
-
3
- // Braille-pattern spinner — the canonical TUI activity indicator.
4
- // 10-frame cycle at 80 ms per frame ≈ 12.5 fps, which reads as
5
- // the same gentle rotation you see in `npm install` or
6
- // `gum spin`. Render inline anywhere you'd otherwise reach for a
7
- // CSS circular spinner — they don't belong under this chrome.
8
-
9
- const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
10
-
11
- export interface BrailleSpinnerProps {
12
- // Frame interval in ms. Default 80.
13
- intervalMs?: number;
14
- // Stop / start cycling. Default true.
15
- active?: boolean;
16
- className?: string;
17
- style?: React.CSSProperties;
18
- }
19
-
20
- export function BrailleSpinner({
21
- intervalMs = 80,
22
- active = true,
23
- className,
24
- style,
25
- }: BrailleSpinnerProps) {
26
- const [i, setI] = useState(0);
27
- useEffect(() => {
28
- if (!active) return;
29
- const t = setInterval(() => setI((x) => (x + 1) % FRAMES.length), intervalMs);
30
- return () => clearInterval(t);
31
- }, [intervalMs, active]);
32
- return (
33
- <span
34
- aria-label="loading"
35
- className={className}
36
- style={{
37
- fontFamily: "var(--ck-font-mono)",
38
- display: "inline-block",
39
- width: "1ch",
40
- ...style,
41
- }}
42
- >
43
- {FRAMES[i]}
44
- </span>
45
- );
46
- }
@@ -1,4 +0,0 @@
1
- export { BrailleSpinner } from "./BrailleSpinner";
2
- export type { BrailleSpinnerProps } from "./BrailleSpinner";
3
- export { AsciiBox } from "./AsciiBox";
4
- export type { AsciiBoxProps } from "./AsciiBox";
@@ -1,99 +0,0 @@
1
- import {
2
- useCallback,
3
- useEffect,
4
- useMemo,
5
- useState,
6
- type ReactNode,
7
- } from "react";
8
- import { ThemeContext } from "./theme-context";
9
- import { BUILTIN_CHROMES } from "./types";
10
- import type { Theme, Chrome, ThemeContextValue } from "./types";
11
-
12
- const DEFAULT_THEME_KEY = "ck-theme";
13
- const DEFAULT_CHROME_KEY = "ck-chrome";
14
-
15
- function readStored<T extends string>(
16
- key: string,
17
- allowed: readonly T[],
18
- ): T | null {
19
- if (typeof window === "undefined") return null;
20
- const v = window.localStorage.getItem(key);
21
- return allowed.includes(v as T) ? (v as T) : null;
22
- }
23
-
24
- function preferredTheme(defaultTheme: Theme | "system"): Theme {
25
- if (defaultTheme !== "system") return defaultTheme;
26
- if (typeof window === "undefined") return "light";
27
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
28
- }
29
-
30
- function applyTheme(theme: Theme, storageKey: string) {
31
- document.documentElement.setAttribute("data-ck-theme", theme);
32
- window.localStorage.setItem(storageKey, theme);
33
- }
34
-
35
- function applyChrome(chrome: Chrome, storageKey: string) {
36
- document.documentElement.setAttribute("data-ck-chrome", chrome);
37
- window.localStorage.setItem(storageKey, chrome);
38
- }
39
-
40
- export interface ThemeProviderProps {
41
- children: ReactNode;
42
- // Initial theme if nothing's in localStorage. "system" reads
43
- // `prefers-color-scheme`; explicit "light" / "dark" forces it.
44
- defaultTheme?: Theme | "system";
45
- defaultChrome?: Chrome;
46
- // localStorage keys — override these per-consumer-app so a host
47
- // page with multiple sub-apps doesn't collide.
48
- themeStorageKey?: string;
49
- chromeStorageKey?: string;
50
- }
51
-
52
- export function ThemeProvider({
53
- children,
54
- defaultTheme = "system",
55
- defaultChrome = "seamless",
56
- themeStorageKey = DEFAULT_THEME_KEY,
57
- chromeStorageKey = DEFAULT_CHROME_KEY,
58
- }: ThemeProviderProps) {
59
- // Initial values match what getInlineThemeScript() would have
60
- // painted on the <html> element pre-mount, so the React tree
61
- // hydrates without a flash.
62
- const [theme, setThemeState] = useState<Theme>(() => {
63
- const stored = readStored<Theme>(themeStorageKey, ["light", "dark"]);
64
- return stored ?? preferredTheme(defaultTheme);
65
- });
66
- const [chrome, setChromeState] = useState<Chrome>(() => {
67
- // Allow every built-in chrome out of localStorage. Custom strings
68
- // (the `(string & {})` half of the Chrome union) are not
69
- // persisted across reloads — consumers that ship custom chromes
70
- // can opt-in via a separate localStorage write upstream of this
71
- // provider if they want persistence.
72
- const stored = readStored<Chrome>(chromeStorageKey, BUILTIN_CHROMES);
73
- return stored ?? defaultChrome;
74
- });
75
-
76
- // Mirror state → DOM. Inline script already set the attribute
77
- // pre-mount; this useEffect handles subsequent runtime changes.
78
- useEffect(() => {
79
- applyTheme(theme, themeStorageKey);
80
- }, [theme, themeStorageKey]);
81
-
82
- useEffect(() => {
83
- applyChrome(chrome, chromeStorageKey);
84
- }, [chrome, chromeStorageKey]);
85
-
86
- const setTheme = useCallback((next: Theme) => setThemeState(next), []);
87
- const setChrome = useCallback((next: Chrome) => setChromeState(next), []);
88
- const toggleTheme = useCallback(
89
- () => setThemeState((t) => (t === "dark" ? "light" : "dark")),
90
- [],
91
- );
92
-
93
- const value = useMemo<ThemeContextValue>(
94
- () => ({ theme, setTheme, toggleTheme, chrome, setChrome }),
95
- [theme, setTheme, toggleTheme, chrome, setChrome],
96
- );
97
-
98
- return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
99
- }
@@ -1,6 +0,0 @@
1
- export { ThemeProvider } from "./ThemeProvider";
2
- export type { ThemeProviderProps } from "./ThemeProvider";
3
- export { useTheme } from "./useTheme";
4
- export { getInlineThemeScript } from "./inline-script";
5
- export { BUILTIN_CHROMES } from "./types";
6
- export type { Theme, Chrome, ThemeContextValue } from "./types";
@@ -1,40 +0,0 @@
1
- import { BUILTIN_CHROMES } from "./types";
2
- import type { Theme, Chrome } from "./types";
3
-
4
- // Pre-mount inline script generator. Paste the returned string
5
- // into a <script> tag in your index.html <head> so the data-ck-*
6
- // attributes are set before React hydrates — prevents a white-
7
- // flash on dark sessions. Pass the same keys you pass to
8
- // <ThemeProvider> so localStorage stays in sync.
9
- //
10
- // Lives in its own file (not co-located with ThemeProvider) so
11
- // React Fast Refresh stays happy — Vite's plugin-react requires
12
- // modules to export only components, and mixing this helper into
13
- // the same file would silently degrade HMR into full reloads (and
14
- // take the data router's in-memory state with it on every save).
15
-
16
- export function getInlineThemeScript(opts: {
17
- themeStorageKey?: string;
18
- chromeStorageKey?: string;
19
- defaultTheme?: Theme | "system";
20
- defaultChrome?: Chrome;
21
- } = {}): string {
22
- const t = JSON.stringify(opts.themeStorageKey ?? "ck-theme");
23
- const c = JSON.stringify(opts.chromeStorageKey ?? "ck-chrome");
24
- const dt = JSON.stringify(opts.defaultTheme ?? "system");
25
- const dc = JSON.stringify(opts.defaultChrome ?? "seamless");
26
- // Inline the allowlist so the runtime check is a single
27
- // Array.indexOf — matches ThemeProvider's readStored behaviour.
28
- const allowed = JSON.stringify(BUILTIN_CHROMES);
29
- return `(function(){try{
30
- var t=localStorage.getItem(${t});
31
- if(t!=="light"&&t!=="dark"){
32
- var d=${dt};
33
- t=d==="system"?(matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"):d;
34
- }
35
- document.documentElement.setAttribute("data-ck-theme",t);
36
- var c=localStorage.getItem(${c});
37
- if(${allowed}.indexOf(c)<0)c=${dc};
38
- document.documentElement.setAttribute("data-ck-chrome",c);
39
- }catch(e){}})();`;
40
- }
@@ -1,7 +0,0 @@
1
- import { createContext } from "react";
2
- import type { ThemeContextValue } from "./types";
3
-
4
- // React Fast Refresh requires component modules to export only
5
- // components. The context object + the hook must therefore live
6
- // in their own files; ThemeProvider.tsx imports from here.
7
- export const ThemeContext = createContext<ThemeContextValue | null>(null);
@@ -1,39 +0,0 @@
1
- // Theme axes. Light/dark is the conventional dark-mode toggle.
2
- // Chrome ("classic" vs "seamless") is an orthogonal style — classic
3
- // has visible borders + subtle dividers, seamless flattens them and
4
- // relies on background shifts for layering. Both axes are applied
5
- // as data attributes on <html>: data-ck-theme, data-ck-chrome.
6
-
7
- export type Theme = "light" | "dark";
8
-
9
- // BUILTIN_CHROMES is the source of truth for "chromes the kit ships
10
- // with". The Chrome union below, the ThemeProvider localStorage
11
- // validator, and the pre-mount inline script all key off this
12
- // constant so adding (or removing) a chrome is a one-place change.
13
- export const BUILTIN_CHROMES = [
14
- "classic",
15
- "seamless",
16
- "editorial",
17
- "neobrutalism",
18
- "ambient",
19
- "swiss",
20
- "terminal",
21
- "bento",
22
- "riso",
23
- "sketch",
24
- ] as const;
25
-
26
- // Built-in chromes ship with the kit; custom strings are also
27
- // allowed at runtime (the kit just stamps the value onto
28
- // `data-ck-chrome`, your CSS supplies the overrides). The
29
- // `(string & {})` trick preserves autocomplete for the built-ins
30
- // while widening the union to any string for custom chromes.
31
- export type Chrome = (typeof BUILTIN_CHROMES)[number] | (string & {});
32
-
33
- export interface ThemeContextValue {
34
- theme: Theme;
35
- setTheme: (next: Theme) => void;
36
- toggleTheme: () => void;
37
- chrome: Chrome;
38
- setChrome: (next: Chrome) => void;
39
- }
@@ -1,8 +0,0 @@
1
- import { useContext } from "react";
2
- import { ThemeContext } from "./theme-context";
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
- }