@sanmid/flux 0.1.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) Sanmid Anavkar
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,88 @@
1
+ # Flux
2
+
3
+ Visual editor overlay for React: inspect the DOM, tweak styles with a live preview, undo/redo, and copy a structured prompt for your AI workflow. **Flux branding only** — no third-party product names in the UI or copy output.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @sanmid/flux lucide-react clsx tailwind-merge framer-motion
9
+ # or: npm / yarn with the same peer dependencies
10
+ ```
11
+
12
+ Peers: `react`, `react-dom` (18+), `lucide-react`, `clsx`, `tailwind-merge`, `framer-motion`.
13
+
14
+ ## Local development (localhost)
15
+
16
+ Mount `DesignEditor` in your app root (providers layout) so it appears over your pages in dev:
17
+
18
+ ```tsx
19
+ "use client";
20
+ import { DesignEditor } from "@sanmid/flux";
21
+
22
+ export function Providers({ children }: { children: React.ReactNode }) {
23
+ return (
24
+ <>
25
+ {children}
26
+ {process.env.NODE_ENV === "development" && <DesignEditor />}
27
+ </>
28
+ );
29
+ }
30
+ ```
31
+
32
+ Open your app at `http://localhost:3000` (or your dev URL). Toggle the editor with the floating control or **⌘.** / **Ctrl+.**
33
+
34
+ - **`force`** — render in production builds (use only if you accept exposing the overlay to end users).
35
+ - **`blockPageInteractions`** — optional; blocks clicks on buttons/links on the host page while editing (useful in demos).
36
+ - **Inline text** — double-click the current selection to edit copy in place (plain text nodes, text-like inputs). Blur commits, **Escape** cancels. Stored with other preview data in `localStorage`. In React apps, a host re-render can still overwrite DOM text until you wire edits into your source of truth.
37
+
38
+ ## Tailwind
39
+
40
+ Include the built bundle in `content` so utilities used inside Flux are generated:
41
+
42
+ ```js
43
+ // tailwind.config.ts
44
+ export default {
45
+ content: [
46
+ "./app/**/*.{ts,tsx}",
47
+ "./components/**/*.{ts,tsx}",
48
+ "./node_modules/@sanmid/flux/dist/index.js",
49
+ ],
50
+ };
51
+ ```
52
+
53
+ ## Next.js
54
+
55
+ ```js
56
+ const nextConfig = {
57
+ transpilePackages: ["@sanmid/flux"],
58
+ };
59
+ ```
60
+
61
+ ## Security
62
+
63
+ See [SECURITY.md](./SECURITY.md) for data handling (clipboard, `localStorage`, DOM), reporting vulnerabilities, and production considerations.
64
+
65
+ ## Publishing to npm (maintainers)
66
+
67
+ 1. **Version** — bump `"version"` in `package.json` (semver).
68
+ 2. **Build** — `pnpm install && pnpm run build` (runs automatically via `prepublishOnly`).
69
+ 3. **Login** — `npm login` (or your registry).
70
+ 4. **Publish** — `npm publish --access public` (required for **scoped** public packages like `@sanmid/flux`).
71
+
72
+ Optional: enable **provenance** on supported registries for supply-chain transparency.
73
+
74
+ ## Playground
75
+
76
+ This repo includes a **private** Vite app under `playground/` for local demos. It is **not** part of the published npm artifact. See [CONTRIBUTING.md](./CONTRIBUTING.md).
77
+
78
+ ```bash
79
+ pnpm run dev:playground
80
+ ```
81
+
82
+ ## Contributing
83
+
84
+ See [CONTRIBUTING.md](./CONTRIBUTING.md).
85
+
86
+ ## License
87
+
88
+ MIT — see [LICENSE](./LICENSE). Other packages on npm may use different licenses (for example Polyform Shield); that is independent of Flux’s license.
package/SECURITY.md ADDED
@@ -0,0 +1,28 @@
1
+ # Security
2
+
3
+ ## Reporting issues
4
+
5
+ Please report security vulnerabilities through **GitHub Security Advisories** for this repository (preferred) or by opening a private discussion with maintainers if that option is unavailable.
6
+
7
+ Do not file public issues for undisclosed vulnerabilities.
8
+
9
+ ## Threat model (npm package)
10
+
11
+ Flux is a **client-side React library** that runs in the browser alongside your app.
12
+
13
+ | Area | Behavior |
14
+ |------|----------|
15
+ | **Network** | The published package does **not** ship telemetry or call remote APIs for core editing. Your app’s own network traffic is unchanged by Flux alone. |
16
+ | **Clipboard** | Copy uses the browser **Clipboard API** / `execCommand('copy')` **after a user gesture** (e.g. clicking Copy). Prompt text reflects DOM and styles under the user’s control. |
17
+ | **Storage** | Preview state may be persisted to **`localStorage`** (namespaced keys) so edits survive reloads during development. Treat stored data as **sensitive as your page content**; clear site data if needed. |
18
+ | **DOM** | The editor injects UI (overlay, panel, drag layers) and may set temporary inline styles during drag/reposition. It applies preview CSS via a stylesheet; review `PreviewEngine` if you extend integration. |
19
+ | **Dependencies** | Runtime deps are limited (see `package.json`). Run `pnpm audit` / `npm audit` in your app and keep peers updated. |
20
+
21
+ ## Production use
22
+
23
+ `DesignEditor` is intended for **development** by default (`NODE_ENV === "development"`). Use `force` only when you understand the risk of exposing a design surface in production.
24
+
25
+ ## Supply chain
26
+
27
+ - Publish from **clean CI** with **npm provenance** if you maintain the package (`npm publish --provenance` on supported registries).
28
+ - Pin lockfiles in apps that consume Flux.
@@ -0,0 +1,241 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type DesignEditorProps = {
4
+ /**
5
+ * When true, the editor mounts in production builds.
6
+ * Default is **development only** (`process.env.NODE_ENV === "development"`).
7
+ */
8
+ force?: boolean;
9
+ /**
10
+ * Classic margin / border / padding overlay bands on the selected node.
11
+ * Default **false** — only the mint selection ring is shown unless you opt in.
12
+ */
13
+ showBoxModel?: boolean;
14
+ /**
15
+ * When the overlay is active, block default actions on interactive page nodes (buttons, links, inputs, …)
16
+ * via capture-phase listeners. Opt-in for host apps (e.g. playgrounds); default **false**.
17
+ */
18
+ blockPageInteractions?: boolean;
19
+ };
20
+ /**
21
+ * Visual design editor overlay. **Does not render in production** unless `force` is set.
22
+ */
23
+ declare function DesignEditor({ force, showBoxModel, blockPageInteractions, }: DesignEditorProps): react_jsx_runtime.JSX.Element | null;
24
+
25
+ /** Persisted for copy prompt after a successful DOM reorder. */
26
+ type FluxStructuralReorder = {
27
+ type: "reorder";
28
+ containerSelector: string;
29
+ containerComponents: string[];
30
+ originalOrder: string[];
31
+ newOrder: string[];
32
+ childrenType: "array" | "static";
33
+ containerSourceFile: {
34
+ fileName: string;
35
+ lineNumber: number;
36
+ columnNumber?: number;
37
+ } | null;
38
+ childSources?: {
39
+ label: string;
40
+ sourceFile: {
41
+ fileName: string;
42
+ lineNumber: number;
43
+ columnNumber?: number;
44
+ };
45
+ }[];
46
+ timestamp: number;
47
+ };
48
+
49
+ /**
50
+ * Live preview engine using Constructable Stylesheets when supported,
51
+ * otherwise a single <style> tag in document.head.
52
+ *
53
+ * Applies CSS changes without mutating the host element's inline styles.
54
+ */
55
+ interface AppliedRule {
56
+ selector: string;
57
+ property: string;
58
+ value: string;
59
+ }
60
+ declare class PreviewEngine {
61
+ private sheet;
62
+ private fallbackStyle;
63
+ private rules;
64
+ private attached;
65
+ constructor();
66
+ attach(): void;
67
+ detach(): void;
68
+ applyChange(selector: string, property: string, value: string): void;
69
+ removeChange(selector: string, property: string): void;
70
+ removeAllChanges(selector: string): void;
71
+ clearAll(): void;
72
+ getChanges(): readonly AppliedRule[];
73
+ /** Last preview value applied for this selector + property (e.g. `100%` when Fill), or undefined. */
74
+ getPreviewValue(selector: string, property: string): string | undefined;
75
+ destroy(): void;
76
+ private flush;
77
+ }
78
+ /**
79
+ * Generate a unique CSS selector for an element using @medv/finder.
80
+ * Falls back to a manual path if finder throws (e.g., SVG elements).
81
+ */
82
+ declare function getUniqueSelector(el: Element): string;
83
+ /**
84
+ * `parent > :nth-child(n)` so preview rules (e.g. `order`) target the exact direct child.
85
+ * Finder-only selectors often collide for sibling elements; this stays stable for flex/grid children.
86
+ */
87
+ declare function getDirectChildSelector(parent: Element, child: Element): string;
88
+ /**
89
+ * Selector used for {@link PreviewEngine} rules. Verifies each candidate with
90
+ * `document.querySelector(sel) === el` so previews (e.g. background) hit the
91
+ * intended node; @medv/finder can occasionally produce a selector that matches
92
+ * a different element. Last resort: a temporary `data-flux-preview-target` id
93
+ * on the element — call {@link removePreviewTargetAttribute} when deselecting.
94
+ */
95
+ declare function getReliableSelectorForPreview(el: Element): {
96
+ selector: string;
97
+ usedAttrFallback: boolean;
98
+ };
99
+ declare function removePreviewTargetAttribute(el: Element | null | undefined): void;
100
+
101
+ interface StyleSnapshot {
102
+ fontFamily: string;
103
+ fontSize: string;
104
+ fontWeight: string;
105
+ lineHeight: string;
106
+ letterSpacing: string;
107
+ color: string;
108
+ textAlign: string;
109
+ width: string;
110
+ height: string;
111
+ padding: string;
112
+ margin: string;
113
+ paddingTop: string;
114
+ paddingRight: string;
115
+ paddingBottom: string;
116
+ paddingLeft: string;
117
+ marginTop: string;
118
+ marginRight: string;
119
+ marginBottom: string;
120
+ marginLeft: string;
121
+ /** CSS `position` (static, relative, absolute, fixed, sticky). */
122
+ position: string;
123
+ /** Inset offsets for positioned layout (`top` / `right` / `bottom` / `left`). */
124
+ top: string;
125
+ right: string;
126
+ bottom: string;
127
+ left: string;
128
+ /** CSS `align-self` — item alignment in flex/grid. */
129
+ alignSelf: string;
130
+ /** CSS `justify-self` — grid item alignment on row axis. */
131
+ justifySelf: string;
132
+ overflow: string;
133
+ display: string;
134
+ flexDirection: string;
135
+ justifyContent: string;
136
+ alignItems: string;
137
+ gap: string;
138
+ rowGap: string;
139
+ columnGap: string;
140
+ gridTemplateColumns: string;
141
+ gridTemplateRows: string;
142
+ backgroundColor: string;
143
+ /** Computed `background-image` (gradients count as fill for `hasFill`-style checks). */
144
+ backgroundImage: string;
145
+ borderTopWidth: string;
146
+ borderRightWidth: string;
147
+ borderBottomWidth: string;
148
+ borderLeftWidth: string;
149
+ borderTopLeftRadius: string;
150
+ borderTopRightRadius: string;
151
+ borderBottomRightRadius: string;
152
+ borderBottomLeftRadius: string;
153
+ borderTopColor: string;
154
+ borderRightColor: string;
155
+ borderBottomColor: string;
156
+ borderLeftColor: string;
157
+ borderTopStyle: string;
158
+ borderRightStyle: string;
159
+ borderBottomStyle: string;
160
+ borderLeftStyle: string;
161
+ borderColor: string;
162
+ borderRadius: string;
163
+ borderStyle: string;
164
+ boxShadow: string;
165
+ opacity: string;
166
+ }
167
+ type DesignEditorElement = Element & {
168
+ style: CSSStyleDeclaration;
169
+ };
170
+ declare function isStyleableElement(target: EventTarget | null): target is DesignEditorElement;
171
+ declare function getComputedSnapshot(el: Element): StyleSnapshot;
172
+ declare function getElementPath(el: Element): string;
173
+ declare function getElementSelector(el: Element): string;
174
+
175
+ /**
176
+ * Border-box dimensions in viewport CSS pixels, rounded for the overlay label.
177
+ */
178
+ declare function formatSelectionDimensions(width: number, height: number): string;
179
+
180
+ /**
181
+ * React fiber traversal for extracting component hierarchy and source file locations.
182
+ * Works with React 18+ dev builds that attach `__reactFiber$` to DOM nodes.
183
+ */
184
+ interface ReactComponentInfo {
185
+ components: string[];
186
+ sourceFile: {
187
+ fileName: string;
188
+ lineNumber: number;
189
+ columnNumber?: number;
190
+ } | null;
191
+ }
192
+ declare function getExactSourceLocation(el: Element): string | null;
193
+ declare function getReactComponentStack(el: Element): string | null;
194
+ declare function getReactComponentInfo(el: Element): ReactComponentInfo;
195
+
196
+ /**
197
+ * Lazy token scanner — walks document.styleSheets to discover CSS custom properties
198
+ * and utility class tokens. Scans on-demand per category, cached until stylesheet count changes.
199
+ */
200
+ type TokenCategory = "colors" | "spacing" | "typography" | "borders" | "effects" | "layout";
201
+ type CssFramework = "tailwind" | "css-modules" | "custom" | "unknown";
202
+ interface DesignToken {
203
+ className: string;
204
+ property: string;
205
+ value: string;
206
+ category: TokenCategory;
207
+ }
208
+ interface CssVariable {
209
+ name: string;
210
+ value: string;
211
+ category: TokenCategory;
212
+ }
213
+ interface TokenScanResult {
214
+ tokens: DesignToken[];
215
+ variables: CssVariable[];
216
+ framework: CssFramework;
217
+ }
218
+ declare function scanTokens(): TokenScanResult;
219
+ /** One-line summary for AI prompts (design-token preamble). */
220
+ declare function summarizeTokenSystem(): string | null;
221
+ declare function detectFramework(): CssFramework;
222
+ declare function getTokensForProperty(cssProperty: string): DesignToken[];
223
+ declare function getVariablesForProperty(cssProperty: string): CssVariable[];
224
+ /**
225
+ * Variables that appear in real CSS rules for this property first, then category fallback.
226
+ */
227
+ declare function getVariablesForPropertySmart(cssPropertyKebab: string): CssVariable[];
228
+
229
+ /**
230
+ * Maps CSS property names (kebab-case) to custom property names that appear
231
+ * in stylesheet values via var(--name), so pickers can prefer vars actually
232
+ * used for that property in the host app.
233
+ */
234
+ declare function invalidateVariableUsageCache(): void;
235
+ /** Custom property names (--foo) that appear in rules for this CSS property. */
236
+ declare function getVariablesUsedForCssProperty(kebabProperty: string): string[];
237
+
238
+ /** Collect `font-family` values from parsed stylesheets (best-effort; skips cross-origin). */
239
+ declare function scanStylesheetFontFamilies(): string[];
240
+
241
+ export { type CssFramework, type CssVariable, DesignEditor, type DesignEditorElement, type DesignEditorProps, type DesignToken, type FluxStructuralReorder, PreviewEngine, type ReactComponentInfo, type StyleSnapshot, type TokenCategory, type TokenScanResult, detectFramework, formatSelectionDimensions, getComputedSnapshot, getDirectChildSelector, getElementPath, getElementSelector, getExactSourceLocation, getReactComponentInfo, getReactComponentStack, getReliableSelectorForPreview, getTokensForProperty, getUniqueSelector, getVariablesForProperty, getVariablesForPropertySmart, getVariablesUsedForCssProperty, invalidateVariableUsageCache, isStyleableElement, removePreviewTargetAttribute, scanStylesheetFontFamilies, scanTokens, summarizeTokenSystem };