@bysages/core 0.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 By Sages
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # @bysages/core
2
+
3
+ ![npm version](https://img.shields.io/npm/v/@bysages/core)
4
+ ![npm downloads](https://img.shields.io/npm/dw/@bysages/core)
5
+ ![npm license](https://img.shields.io/npm/l/@bysages/core)
6
+
7
+ > The visual core of By Sages Elements: the only style layer of the design system, the theme engine, and the lighting engine β€” framework-agnostic, consumed by every wrapper package.
8
+
9
+ ## Features
10
+
11
+ - 🎨 **The only visual layer** β€” every component's stylesheet lives here, native CSS scoped by `[data-scope][data-part]`, so one stylesheet serves React, Vue, Solid, and Svelte alike
12
+ - πŸŒ— **Theme engine** β€” `applyTheme()` drives light/dark, accent pigments (qinghua / celadon / zhusha), contrast tiers, density tiers, and scene presets, all expressed as data on the document root
13
+ - πŸ’‘ **Lighting engine** β€” elevation, pigment bleed, and pointer-carried light computed into CSS variables (`setLight`, `attachDynamicLight`); component styles only ever consume light (δ»₯ε…‰δΈΊε½± β€” light as shadow)
14
+ - πŸ–‹οΈ **Ink ripple** β€” a press feedback pass that bleeds pigment from the pointer, delegated at the root and tuneable per element
15
+ - 🧩 **Style injection** β€” `injectComponentStyle()` ships each family's stylesheet at import time, guarded by a head marker so SSR builds that inline styles never double-inject
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ # pnpm
21
+ pnpm add @bysages/core @bysages/tokens
22
+
23
+ # npm
24
+ npm install @bysages/core @bysages/tokens
25
+
26
+ # yarn
27
+ yarn add @bysages/core @bysages/tokens
28
+
29
+ # bun
30
+ bun add @bysages/core @bysages/tokens
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ Load the compiled tokens, theme the document, and the component styles arrive with the wrappers:
36
+
37
+ ```ts
38
+ import "@bysages/tokens/css";
39
+ import { applyTheme, attachDynamicLight } from "@bysages/core";
40
+
41
+ applyTheme({ mode: "system", accent: "ink", density: "default" });
42
+ attachDynamicLight();
43
+ ```
44
+
45
+ ## Architecture
46
+
47
+ ```
48
+ @bysages/tokens DTCG source β†’ CSS custom properties
49
+ ↓
50
+ @bysages/core theme engine Β· lighting engine Β· per-component styles
51
+ ↓
52
+ wrappers Vue Β· React Β· Solid Β· Svelte β€” thin adapters over headless machines
53
+ ```
54
+
55
+ The core owns no interaction; it renders nothing but light. Wrappers bring the headless state machines, the core dresses them.
56
+
57
+ ## License
58
+
59
+ - [MIT](../../LICENSE) Β© [By Sages](https://www.bysages.com/)
@@ -0,0 +1,131 @@
1
+ //#region src/theme.d.ts
2
+ /**
3
+ * Theme engine β€” the runtime half of the token system. Tokens declare how
4
+ * themes look (`@layer bs.tokens`); this module drives which theme is active
5
+ * via data attributes on the root element: `data-theme`, `data-contrast`,
6
+ * `data-density`, `data-scene`, and `data-accent`.
7
+ *
8
+ * @module
9
+ */
10
+ export type ThemeMode = "light" | "dark" | "system";
11
+ export type ThemeContrast = "auto" | "normal" | "high";
12
+ export type ThemeDensity = "compact" | "default" | "comfortable" | "spacious";
13
+ export type ThemeScene = "auto" | "civic" | "enterprise" | "studio" | "tech";
14
+ export type ThemeAccent = "auto" | "ink" | "qinghua" | "celadon" | "zhusha";
15
+ export interface Theme {
16
+ mode: ThemeMode;
17
+ contrast: ThemeContrast;
18
+ density: ThemeDensity;
19
+ scene: ThemeScene;
20
+ accent: ThemeAccent;
21
+ }
22
+ /** Each scene pairs with a default accent β€” the pigment that carries its
23
+ * context (civic identity is zhusha, never an error color; tech stays
24
+ * ink). "auto" accent resolves through this table; explicit accents win. */
25
+ export declare const SCENE_DEFAULT_ACCENT: Record<Exclude<ThemeScene, "auto">, ThemeAccent>;
26
+ /** Each scene also pairs with a contrast tier β€” civic serves elders, so it
27
+ * speaks at the loud tier by default. "auto" contrast resolves here;
28
+ * explicit choices win. */
29
+ export declare const SCENE_DEFAULT_CONTRAST: Record<Exclude<ThemeScene, "auto">, "normal" | "high">;
30
+ export interface ApplyThemeOptions extends Partial<Theme> {
31
+ /** Persist the theme to localStorage so `initTheme` can restore it. Defaults to true. */
32
+ persist?: boolean;
33
+ }
34
+ /**
35
+ * Apply a theme to the document root. Omitted fields keep the current value;
36
+ * `mode: "system"` resolves against `prefers-color-scheme`, and an "auto"
37
+ * accent resolves against the active scene.
38
+ */
39
+ export declare function applyTheme(options?: ApplyThemeOptions): Theme;
40
+ /** Read the active theme (in-memory state first, then root attributes,
41
+ * then storage). */
42
+ export declare function getTheme(): Theme;
43
+ /**
44
+ * Restore the persisted theme and keep `mode: "system"` in sync with the OS
45
+ * while it is active. Safe to call more than once; SSR is a no-op.
46
+ */
47
+ export declare function initTheme(): void;
48
+ //#endregion
49
+ //#region src/lighting.d.ts
50
+ /**
51
+ * Lighting engine β€” the dynamic half of the light pipeline. Every elevation
52
+ * token computes its shadow from four CSS variables (`--bs-light-x/-y`,
53
+ * `--bs-light-reach`, `--bs-shadow-ink`), so writing those variables re-lights
54
+ * the whole interface and every component follows without owning any shadow
55
+ * code of its own.
56
+ *
57
+ * `setLight` places the key light once (a scene's bundled light, or an
58
+ * application's choice). `attachDynamicLight` lets the pointer carry it:
59
+ * the element under the cursor is lit locally, its shadow leaning away from
60
+ * the pointer as the light would cast it.
61
+ *
62
+ * @module
63
+ */
64
+ export interface LightState {
65
+ /** Shadow offset along x β€” the direction the light pushes away from. */
66
+ x?: string;
67
+ /** Shadow offset along y. */
68
+ y?: string;
69
+ /** How far shadows spread; multiplies every elevation's reach. */
70
+ reach?: number;
71
+ /** Shadow hue, any CSS color (themes use oklch). */
72
+ ink?: string;
73
+ }
74
+ /** Place the key light on the document root. Omitted parts keep their
75
+ * current value. Inline styles set here outrank scene and theme defaults. */
76
+ export declare function setLight(state: LightState): void;
77
+ /** Read the key light currently in force on the document root. */
78
+ export declare function getLight(): LightState;
79
+ /** Remove the inline light so theme and scene declarations take over. */
80
+ export declare function resetLight(): void;
81
+ export interface DynamicLightOptions {
82
+ /** Largest shadow shift, in px, when the pointer sits at an element's
83
+ * edge. Defaults to 3 β€” enough to feel alive, never enough to wobble. */
84
+ strength?: number;
85
+ }
86
+ /** Let the pointer carry the light across every lit element. Skips touch
87
+ * pointers and honors `prefers-reduced-motion`; safe to call more than
88
+ * once (the previous listener is replaced). Returns the detach function. */
89
+ export declare function attachDynamicLight(options?: DynamicLightOptions): () => void;
90
+ /** Stop the pointer from carrying the light and clear any local shifts. */
91
+ export declare function detachDynamicLight(): void;
92
+ //#endregion
93
+ //#region src/ink-ripple.d.ts
94
+ /**
95
+ * Ink ripple β€” the press feedback of the paper-and-ink register. Where
96
+ * Material spreads a hard circle, ink bleeds: a soft wash of the element's
97
+ * own pigment diluting outward from the press point, gone before it draws
98
+ * attention to itself.
99
+ *
100
+ * The bleed's CSS lives in the base stylesheet, keyed on
101
+ * `data-motion~="ink-ripple"`; this module watches presses and marks the
102
+ * press point. Reduced motion collapses the bleed to a state change, as
103
+ * everywhere else in the system.
104
+ *
105
+ * @module
106
+ */
107
+ /** Watch for presses anywhere inside `root` (default: the document) and
108
+ * bleed ink from the press point of the nearest opt-in element. Safe to
109
+ * call more than once; returns the detach function. */
110
+ export declare function attachInkRipple(root?: HTMLElement): () => void;
111
+ /** Stop watching presses. */
112
+ export declare function detachInkRipple(): void;
113
+ //#endregion
114
+ //#region src/styles/components/index.d.ts
115
+ /** Component style registry β€” every component contributes its stylesheet
116
+ * here, keyed by the name wrappers pass to `injectComponentStyle`. */
117
+ export declare const componentStyles: Record<string, string>;
118
+ //#endregion
119
+ //#region src/styles.d.ts
120
+ /** The complete token layer (`@layer bs.tokens`): themes, density, contrast,
121
+ * typography, motion, z-index, plus the document-level base guard and the
122
+ * ink-ripple motion grammar. */
123
+ export declare const tokensCss: string;
124
+ /** Inject the token layer into the document head once β€” the inheritance
125
+ * root that carries themes, density, and the motion grammar. SSR is a
126
+ * no-op; for SSR pass `tokensCss` to a head tag instead. */
127
+ export declare function injectTokens(): void;
128
+ /** Inject one component stylesheet (plus the token layer on first use).
129
+ * Idempotent per component; SSR is a no-op. */
130
+ export declare function injectComponentStyle(key: string): void;
131
+ //#endregion