@aspicio/elements
Advanced tools
+63
-4
@@ -5,4 +5,6 @@ import { LitElement, PropertyValues, TemplateResult } from "lit"; | ||
| //#region src/theme.d.ts | ||
| /** Visual theme for the ready-made elements. */ | ||
| /** Whether the ready-made elements style themselves at all. */ | ||
| type AspicioTheme = "aspicio" | "none"; | ||
| /** Which palette a styled element uses (ELEM-10). */ | ||
| type AspicioThemeMode = "dark" | "light"; | ||
| /** | ||
@@ -17,2 +19,6 @@ * Design tokens lifted from the Aspicio demo app, exposed as CSS custom | ||
| * system faces. | ||
| * | ||
| * This object is the single source for the CSS below: the declarations are | ||
| * generated from it rather than hand-copied beside it, because they were | ||
| * hand-copied beside it and the two drifted the moment a token was added. | ||
| */ | ||
@@ -29,3 +35,3 @@ declare const aspicioTokens: { | ||
| readonly text2: "#9aa0ab"; | ||
| readonly text3: "#6a707b"; | ||
| readonly text3: "#7f858f"; | ||
| readonly crease: "#4c8dff"; | ||
@@ -35,6 +41,47 @@ readonly creasedim: "rgba(76,141,255,.16)"; | ||
| readonly amberdim: "rgba(224,168,46,.16)"; | ||
| readonly amberborder: "rgba(224,168,46,.4)"; | ||
| readonly amberborder: "rgba(224,168,46,.4)"; /** Everything outside the paper. The darkest region after the app frame. */ | ||
| readonly surround: "#0d0f13"; | ||
| readonly gridMinor: "rgba(255,255,255,.028)"; | ||
| readonly gridMajor: "rgba(255,255,255,.05)"; | ||
| readonly fontSans: '"IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif'; | ||
| readonly fontMono: '"IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace'; | ||
| }; | ||
| /** Every token name, with values free to differ per palette. */ | ||
| type AspicioTokens = Record<keyof typeof aspicioTokens, string>; | ||
| /** | ||
| * The light palette. Same names, same intent — not the dark one inverted. | ||
| * | ||
| * `text` is a deliberately warm off-white, so its counterpart is a warm | ||
| * near-black rather than a blue-black; no chrome surface goes above #f7f5f1, | ||
| * which is reserved for raised panels. Accents move because they have to: | ||
| * #4c8dff is 3.2:1 on light chrome and #e0a82e is 1.8:1, both below AA. | ||
| * | ||
| * `sheet` is the one token that does not change. In light mode the only pure | ||
| * white on screen is the paper, which is what keeps it reading as a discrete | ||
| * object on a surface rather than merging into the chrome around it. | ||
| */ | ||
| declare const aspicioLightTokens: AspicioTokens; | ||
| /** | ||
| * Canvas colours the *renderer* needs as numbers rather than CSS. | ||
| * | ||
| * The sheet is WebGL geometry, not a DOM surface, so it cannot come from a | ||
| * custom property. Deriving both from one palette keeps the paper on the | ||
| * canvas and the paper in the CSS from drifting apart. | ||
| */ | ||
| interface AspicioCanvasColors { | ||
| /** Paper under a bounded space. White in both palettes: in a PDF the sheet | ||
| * is the *unpainted* region, so a tint would make 0/0/0/0 white artwork | ||
| * show as a rectangle against the paper it is meant to match. */ | ||
| sheet: number; | ||
| /** Sheet boundary, or null when contrast alone carries it. */ | ||
| sheetEdge: number | null; | ||
| /** Selection over an unbounded canvas, and over paper (VIEW-8). */ | ||
| select: number; | ||
| selectOnSheet: number; | ||
| /** Canvas that DXF pen colours must stay legible against (VIEW-18). */ | ||
| legibleOn?: number; | ||
| /** What a hueless pen darkens towards under `legibleOn`. */ | ||
| ink?: number; | ||
| } | ||
| declare const aspicioCanvasColors: Record<AspicioThemeMode, AspicioCanvasColors>; | ||
| //#endregion | ||
@@ -78,2 +125,7 @@ //#region src/aspicio-embed.d.ts | ||
| }; | ||
| themeMode: { | ||
| type: StringConstructor; | ||
| attribute: string; | ||
| reflect: boolean; | ||
| }; | ||
| panelStyle: { | ||
@@ -101,2 +153,3 @@ attribute: boolean; | ||
| theme: AspicioTheme; | ||
| themeMode: AspicioThemeMode; | ||
| panelStyle: Partial<CSSStyleDeclaration> | undefined; | ||
@@ -139,2 +192,7 @@ noDownload: boolean; | ||
| }; | ||
| themeMode: { | ||
| type: StringConstructor; | ||
| attribute: string; | ||
| reflect: boolean; | ||
| }; | ||
| reverseHighlightLayer: { | ||
@@ -160,2 +218,3 @@ type: StringConstructor; | ||
| theme: AspicioTheme; | ||
| themeMode: AspicioThemeMode; | ||
| reverseHighlightLayer: string | null; | ||
@@ -253,2 +312,2 @@ noHints: boolean; | ||
| //#endregion | ||
| export { AspicioEmbed, AspicioLayerPanel, AspicioPreview, type AspicioTheme, type LoadedDetail, type PanelSide, aspicioTokens }; | ||
| export { type AspicioCanvasColors, AspicioEmbed, AspicioLayerPanel, AspicioPreview, type AspicioTheme, type AspicioThemeMode, type AspicioTokens, type LoadedDetail, type PanelSide, aspicioCanvasColors, aspicioLightTokens, aspicioTokens }; |
+123
-30
| import { n as registeredFormats } from "./formats-DYIkYS6H.mjs"; | ||
| import { LitElement, css, html, nothing } from "lit"; | ||
| import { LitElement, css, html, nothing, unsafeCSS } from "lit"; | ||
| import { DrawingParseError, DrawingViewer, attachShortcuts } from "@aspicio/core"; | ||
@@ -14,2 +14,6 @@ //#region src/theme.ts | ||
| * system faces. | ||
| * | ||
| * This object is the single source for the CSS below: the declarations are | ||
| * generated from it rather than hand-copied beside it, because they were | ||
| * hand-copied beside it and the two drifted the moment a token was added. | ||
| */ | ||
@@ -26,3 +30,3 @@ const aspicioTokens = { | ||
| text2: "#9aa0ab", | ||
| text3: "#6a707b", | ||
| text3: "#7f858f", | ||
| crease: "#4c8dff", | ||
@@ -33,2 +37,6 @@ creasedim: "rgba(76,141,255,.16)", | ||
| amberborder: "rgba(224,168,46,.4)", | ||
| /** Everything outside the paper. The darkest region after the app frame. */ | ||
| surround: "#0d0f13", | ||
| gridMinor: "rgba(255,255,255,.028)", | ||
| gridMajor: "rgba(255,255,255,.05)", | ||
| fontSans: "\"IBM Plex Sans\", system-ui, -apple-system, \"Segoe UI\", sans-serif", | ||
@@ -38,28 +46,79 @@ fontMono: "\"IBM Plex Mono\", ui-monospace, \"SF Mono\", Menlo, monospace" | ||
| /** | ||
| * The light palette. Same names, same intent — not the dark one inverted. | ||
| * | ||
| * `text` is a deliberately warm off-white, so its counterpart is a warm | ||
| * near-black rather than a blue-black; no chrome surface goes above #f7f5f1, | ||
| * which is reserved for raised panels. Accents move because they have to: | ||
| * #4c8dff is 3.2:1 on light chrome and #e0a82e is 1.8:1, both below AA. | ||
| * | ||
| * `sheet` is the one token that does not change. In light mode the only pure | ||
| * white on screen is the paper, which is what keeps it reading as a discrete | ||
| * object on a surface rather than merging into the chrome around it. | ||
| */ | ||
| const aspicioLightTokens = { | ||
| bg: "#e6e3dd", | ||
| canvas: "#dcd8d1", | ||
| panel: "#efece6", | ||
| panel2: "#f7f5f1", | ||
| hover: "rgba(0,0,0,.05)", | ||
| hairline: "#dbd6cd", | ||
| hairline2: "#b6b0a5", | ||
| text: "#1c1a17", | ||
| text2: "#3f3c36", | ||
| text3: "#605c54", | ||
| crease: "#1a63d8", | ||
| creasedim: "rgba(26,99,216,.12)", | ||
| amber: "#8a6209", | ||
| amberdim: "rgba(138,98,9,.14)", | ||
| amberborder: "rgba(138,98,9,.4)", | ||
| surround: "#c4c4c4", | ||
| gridMinor: "rgba(0,0,0,.035)", | ||
| gridMajor: "rgba(0,0,0,.065)", | ||
| fontSans: aspicioTokens.fontSans, | ||
| fontMono: aspicioTokens.fontMono | ||
| }; | ||
| const aspicioCanvasColors = { | ||
| dark: { | ||
| sheet: 16777215, | ||
| sheetEdge: null, | ||
| select: 9423103, | ||
| selectOnSheet: 2848968 | ||
| }, | ||
| light: { | ||
| sheet: 16777215, | ||
| sheetEdge: 11053224, | ||
| select: 2848968, | ||
| selectOnSheet: 2848968, | ||
| legibleOn: 14473425, | ||
| ink: 1841687 | ||
| } | ||
| }; | ||
| /** `fontSans` → `--aspicio-font-sans`. */ | ||
| const cssName = (key) => `--aspicio-${key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`; | ||
| const declarations = (tokens) => unsafeCSS(Object.entries(tokens).map(([key, value]) => `${cssName(key)}: ${value};`).join("\n ")); | ||
| /** | ||
| * Custom-property declarations with token defaults. Included in every | ||
| * element's static styles so `var(--aspicio-*)` always resolves, while a | ||
| * host-page rule on the element (or any ancestor, via inheritance) wins. | ||
| * | ||
| * Dark is the bare `:host` rule so an element with no mode set keeps | ||
| * rendering exactly as it always has. | ||
| */ | ||
| const tokenStyles = css` | ||
| :host { | ||
| --aspicio-bg: #0f1115; | ||
| --aspicio-canvas: #16181d; | ||
| --aspicio-panel: #191c22; | ||
| --aspicio-panel2: #1f232b; | ||
| --aspicio-hover: rgba(255, 255, 255, 0.055); | ||
| --aspicio-hairline: #282c34; | ||
| --aspicio-hairline2: #3a3f4a; | ||
| --aspicio-text: #e7e3da; | ||
| --aspicio-text2: #9aa0ab; | ||
| --aspicio-text3: #6a707b; | ||
| --aspicio-crease: #4c8dff; | ||
| --aspicio-creasedim: rgba(76, 141, 255, 0.16); | ||
| --aspicio-amber: #e0a82e; | ||
| --aspicio-amberdim: rgba(224, 168, 46, 0.16); | ||
| --aspicio-amberborder: rgba(224, 168, 46, 0.4); | ||
| --aspicio-font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; | ||
| --aspicio-font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace; | ||
| ${declarations(aspicioTokens)} | ||
| } | ||
| :host([theme-mode="light"]) { | ||
| ${declarations(aspicioLightTokens)} | ||
| } | ||
| `; | ||
| /** The demo app's blueprint grid, drawn behind a transparent canvas. */ | ||
| /** | ||
| * The blueprint grid, drawn behind a transparent canvas. | ||
| * | ||
| * `.page-mode` drops it. The grid's job is parallax and scale feedback in | ||
| * unbounded model space; a bounded page already provides both, and keeping | ||
| * it would run a repeating pattern up to the one line the reader has to | ||
| * trust — the sheet edge — and put it beside artwork being colour-judged. | ||
| */ | ||
| const canvasBackgroundStyles = css` | ||
@@ -69,6 +128,6 @@ .canvas-grid { | ||
| background-image: | ||
| linear-gradient(rgba(255, 255, 255, 0.028) 1px, transparent 1px), | ||
| linear-gradient(90deg, rgba(255, 255, 255, 0.028) 1px, transparent 1px), | ||
| linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px), | ||
| linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px); | ||
| linear-gradient(var(--aspicio-grid-minor) 1px, transparent 1px), | ||
| linear-gradient(90deg, var(--aspicio-grid-minor) 1px, transparent 1px), | ||
| linear-gradient(var(--aspicio-grid-major) 1px, transparent 1px), | ||
| linear-gradient(90deg, var(--aspicio-grid-major) 1px, transparent 1px); | ||
| background-size: | ||
@@ -80,2 +139,7 @@ 26px 26px, | ||
| } | ||
| .canvas-grid.page-mode { | ||
| background-color: var(--aspicio-surround); | ||
| background-image: none; | ||
| } | ||
| `; | ||
@@ -112,2 +176,7 @@ //#endregion | ||
| }, | ||
| themeMode: { | ||
| type: String, | ||
| attribute: "theme-mode", | ||
| reflect: true | ||
| }, | ||
| panelStyle: { attribute: false }, | ||
@@ -129,2 +198,3 @@ noDownload: { | ||
| this.theme = "aspicio"; | ||
| this.themeMode = "dark"; | ||
| this.panelStyle = void 0; | ||
@@ -200,7 +270,21 @@ this.noDownload = false; | ||
| #previewOptions() { | ||
| return this.theme !== "none" && this.options?.background === void 0 ? { | ||
| ...this.options, | ||
| background: null | ||
| } : this.options; | ||
| if (!(this.theme !== "none")) return this.options; | ||
| const canvas = aspicioCanvasColors[this.themeMode] ?? aspicioCanvasColors.dark; | ||
| return { | ||
| ...this.options?.background === void 0 ? { background: null } : {}, | ||
| ...canvas, | ||
| ...this.options | ||
| }; | ||
| } | ||
| /** | ||
| * True when the space on screen is a bounded page. | ||
| * | ||
| * Drives the grid: an infinite blueprint grid is scale feedback for | ||
| * unbounded model space, and a page provides that itself through its own | ||
| * edge. Read from the viewer rather than from the file format, because a | ||
| * PDF page whose box would not read has no sheet to key off. | ||
| */ | ||
| get #hasPage() { | ||
| return this._viewer?.activePage != null; | ||
| } | ||
| #renderPanel() { | ||
@@ -214,2 +298,3 @@ if (this.panel === "none") return nothing; | ||
| theme=${this.theme} | ||
| theme-mode=${this.themeMode} | ||
| .viewer=${this._viewer} | ||
@@ -224,3 +309,5 @@ reverse-highlight-layer=${this._reverseHighlight ?? nothing} | ||
| ${this.panel === "left" ? this.#renderPanel() : nothing} | ||
| <div class="canvas-wrap ${themed ? "canvas-grid" : ""}"> | ||
| <div | ||
| class="canvas-wrap ${themed ? "canvas-grid" : ""} ${themed && this.#hasPage ? "page-mode" : ""}" | ||
| > | ||
| <aspicio-preview | ||
@@ -291,2 +378,7 @@ part="preview" | ||
| theme: { type: String }, | ||
| themeMode: { | ||
| type: String, | ||
| attribute: "theme-mode", | ||
| reflect: true | ||
| }, | ||
| reverseHighlightLayer: { | ||
@@ -313,2 +405,3 @@ type: String, | ||
| this.theme = "aspicio"; | ||
| this.themeMode = "dark"; | ||
| this.reverseHighlightLayer = null; | ||
@@ -1036,2 +1129,2 @@ this.noHints = false; | ||
| //#endregion | ||
| export { AspicioEmbed, AspicioLayerPanel, AspicioPreview, aspicioTokens }; | ||
| export { AspicioEmbed, AspicioLayerPanel, AspicioPreview, aspicioCanvasColors, aspicioLightTokens, aspicioTokens }; |
+3
-3
| { | ||
| "name": "@aspicio/elements", | ||
| "version": "0.12.0", | ||
| "version": "0.13.0", | ||
| "description": "Framework-neutral web components for the Aspicio DXF and PDF viewer.", | ||
@@ -40,3 +40,3 @@ "homepage": "https://github.com/frontsail-ai/aspicio/tree/master/packages/elements#readme", | ||
| "dependencies": { | ||
| "@aspicio/core": "^0.12.0", | ||
| "@aspicio/core": "^0.13.0", | ||
| "lit": "^3.3.3" | ||
@@ -46,3 +46,3 @@ }, | ||
| "@typescript/native-preview": "^7.0.0-dev.20260707.2", | ||
| "happy-dom": "^20.0.0", | ||
| "happy-dom": "^20.11.2", | ||
| "typescript": "^7.0.2", | ||
@@ -49,0 +49,0 @@ "vite-plus": "0.2.4" |
53939
11.61%1172
8.42%+ Added
- Removed
Updated