@cosxai/ui 0.25.0 → 1.0.0-alpha.0

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 (133) hide show
  1. package/CHANGELOG.md +577 -0
  2. package/NOTICE +11 -0
  3. package/README.md +52 -0
  4. package/package.json +33 -7
  5. package/src/fonts.css +20 -0
  6. package/src/index.ts +8 -25
  7. package/src/lib/cn.ts +23 -6
  8. package/src/styles.css +17 -0
  9. package/src/theme.css +132 -0
  10. package/src/tokens/colors.css +112 -0
  11. package/src/tokens/compat.css +36 -0
  12. package/src/tokens/elevation.css +14 -0
  13. package/src/tokens/motion.css +42 -0
  14. package/src/tokens/spacing.css +55 -0
  15. package/src/tokens/typography-cjk.css +42 -0
  16. package/src/tokens/typography.css +81 -0
  17. package/src/actionbar/ActionBar.tsx +0 -837
  18. package/src/actionbar/ActionBarButton.tsx +0 -111
  19. package/src/actionbar/ActionBarMenuGroup.tsx +0 -116
  20. package/src/actionbar/ActionBarModeHandle.tsx +0 -171
  21. package/src/actionbar/ActionBarProvider.tsx +0 -91
  22. package/src/actionbar/actionbar-context.ts +0 -45
  23. package/src/actionbar/index.ts +0 -28
  24. package/src/actionbar/types.ts +0 -147
  25. package/src/actionbar/useActionBarItems.ts +0 -60
  26. package/src/actionbar/useActionBarMode.ts +0 -144
  27. package/src/actionbar/useActionBarPanel.ts +0 -56
  28. package/src/actionbar/useActionBarStatusDot.ts +0 -49
  29. package/src/actionbar/useActionBarToast.ts +0 -33
  30. package/src/ambient/AmbientBackdrop.tsx +0 -74
  31. package/src/ambient/CommandInput.tsx +0 -107
  32. package/src/ambient/SuperbarStrip.tsx +0 -36
  33. package/src/ambient/index.ts +0 -6
  34. package/src/bento/BentoCell.tsx +0 -66
  35. package/src/bento/BentoGrid.tsx +0 -42
  36. package/src/bento/index.ts +0 -2
  37. package/src/command/CommandPalette.tsx +0 -329
  38. package/src/command/CommandProvider.tsx +0 -57
  39. package/src/command/command-context.ts +0 -12
  40. package/src/command/index.ts +0 -6
  41. package/src/command/rank.ts +0 -50
  42. package/src/command/types.ts +0 -37
  43. package/src/command/useCommandSource.ts +0 -37
  44. package/src/dialogs/DialogsProvider.tsx +0 -216
  45. package/src/dialogs/Modal.tsx +0 -260
  46. package/src/dialogs/Toast.tsx +0 -85
  47. package/src/dialogs/dialogs-context.ts +0 -6
  48. package/src/dialogs/index.ts +0 -10
  49. package/src/dialogs/types.ts +0 -37
  50. package/src/dialogs/useDialogs.ts +0 -8
  51. package/src/editorial/EditorialSpotlight.tsx +0 -63
  52. package/src/editorial/Folio.tsx +0 -52
  53. package/src/editorial/PlateMarker.tsx +0 -33
  54. package/src/editorial/RomanSection.tsx +0 -65
  55. package/src/editorial/RunningMarginalia.tsx +0 -65
  56. package/src/editorial/index.ts +0 -10
  57. package/src/hooks/index.ts +0 -5
  58. package/src/hooks/useKeyboardHotkey.ts +0 -93
  59. package/src/hooks/useReducedMotion.ts +0 -20
  60. package/src/hooks/useViewport.ts +0 -61
  61. package/src/layout/Breadcrumb.tsx +0 -74
  62. package/src/layout/LeftNavRail.tsx +0 -139
  63. package/src/layout/MobileTabBar.tsx +0 -101
  64. package/src/layout/NavItem.tsx +0 -128
  65. package/src/layout/NavSearchTrigger.tsx +0 -88
  66. package/src/layout/NavSection.tsx +0 -40
  67. package/src/layout/RightSidebarPanel.tsx +0 -111
  68. package/src/layout/Shell.tsx +0 -91
  69. package/src/layout/SidePanel.tsx +0 -316
  70. package/src/layout/StickyBanner.tsx +0 -83
  71. package/src/layout/Topbar.tsx +0 -68
  72. package/src/layout/index.ts +0 -24
  73. package/src/layout/useNavRailState.ts +0 -69
  74. package/src/lib/time-utils.ts +0 -44
  75. package/src/neobrutalism/Marquee.tsx +0 -81
  76. package/src/neobrutalism/Sticker.tsx +0 -71
  77. package/src/neobrutalism/index.ts +0 -4
  78. package/src/primitives/Avatar.tsx +0 -53
  79. package/src/primitives/Button.tsx +0 -67
  80. package/src/primitives/Card.tsx +0 -41
  81. package/src/primitives/Checkbox.tsx +0 -87
  82. package/src/primitives/Chip.tsx +0 -191
  83. package/src/primitives/Combobox.tsx +0 -507
  84. package/src/primitives/CopyField.tsx +0 -139
  85. package/src/primitives/CountBadge.tsx +0 -50
  86. package/src/primitives/Input.tsx +0 -204
  87. package/src/primitives/Kbd.tsx +0 -45
  88. package/src/primitives/MentionCombobox.tsx +0 -612
  89. package/src/primitives/MultiCombobox.tsx +0 -327
  90. package/src/primitives/PageHeader.tsx +0 -77
  91. package/src/primitives/Radio.tsx +0 -131
  92. package/src/primitives/SegmentedControl.tsx +0 -135
  93. package/src/primitives/Select.tsx +0 -779
  94. package/src/primitives/SignaturePad.tsx +0 -461
  95. package/src/primitives/Tag.tsx +0 -56
  96. package/src/primitives/Textarea.tsx +0 -62
  97. package/src/primitives/ToggleSwitch.tsx +0 -79
  98. package/src/primitives/Tooltip.tsx +0 -213
  99. package/src/primitives/index.ts +0 -53
  100. package/src/pwa/InstallPromptBanner.tsx +0 -132
  101. package/src/pwa/index.ts +0 -4
  102. package/src/pwa/manifest.template.json +0 -20
  103. package/src/pwa/registerSW.ts +0 -55
  104. package/src/riso/Halftone.tsx +0 -85
  105. package/src/riso/Misregister.tsx +0 -63
  106. package/src/riso/RisoStamp.tsx +0 -76
  107. package/src/riso/index.ts +0 -3
  108. package/src/sketch/HandUnderline.tsx +0 -53
  109. package/src/sketch/RoughArrow.tsx +0 -91
  110. package/src/sketch/RoughBox.tsx +0 -73
  111. package/src/sketch/StickyNote.tsx +0 -56
  112. package/src/sketch/index.ts +0 -4
  113. package/src/styles/base.css +0 -186
  114. package/src/styles/chrome-ambient.css +0 -235
  115. package/src/styles/chrome-bento.css +0 -192
  116. package/src/styles/chrome-editorial.css +0 -168
  117. package/src/styles/chrome-neobrutalism.css +0 -326
  118. package/src/styles/chrome-riso.css +0 -339
  119. package/src/styles/chrome-sketch.css +0 -362
  120. package/src/styles/chrome-swiss.css +0 -265
  121. package/src/styles/chrome-terminal.css +0 -272
  122. package/src/styles/fonts.css +0 -1034
  123. package/src/styles/index.css +0 -343
  124. package/src/styles/tokens.css +0 -941
  125. package/src/terminal/AsciiBox.tsx +0 -65
  126. package/src/terminal/BrailleSpinner.tsx +0 -46
  127. package/src/terminal/index.ts +0 -4
  128. package/src/theme/ThemeProvider.tsx +0 -99
  129. package/src/theme/index.ts +0 -6
  130. package/src/theme/inline-script.ts +0 -40
  131. package/src/theme/theme-context.ts +0 -7
  132. package/src/theme/types.ts +0 -39
  133. 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
- }