@gjsify/adwaita-web 0.14.0 → 0.16.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 (49) hide show
  1. package/README.md +58 -0
  2. package/dist/adwaita-web.css +617 -0
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/adw-data-grid.spec.d.ts +1 -0
  5. package/lib/types/adw-dialog.spec.d.ts +1 -0
  6. package/lib/types/adw-drop-down.spec.d.ts +1 -0
  7. package/lib/types/elements/adw-data-grid.d.ts +60 -0
  8. package/lib/types/elements/adw-dialog.d.ts +51 -0
  9. package/lib/types/elements/adw-drop-down.d.ts +63 -0
  10. package/lib/types/elements/adw-menu-button.d.ts +34 -0
  11. package/lib/types/elements/adw-view-stack.d.ts +37 -0
  12. package/lib/types/elements/adw-view-switcher-bar.d.ts +27 -0
  13. package/lib/types/index.d.ts +11 -0
  14. package/lib/types/source-view/adw-source-view.d.ts +75 -0
  15. package/lib/types/source-view/asm6502.d.ts +28 -0
  16. package/lib/types/source-view/hex.d.ts +27 -0
  17. package/lib/types/source-view/index.d.ts +4 -0
  18. package/lib/types/source-view/theme.d.ts +15 -0
  19. package/lib/types/styles.generated.d.ts +1 -1
  20. package/package.json +24 -12
  21. package/scss/_data_grid.scss +144 -0
  22. package/scss/_dialog.scss +220 -0
  23. package/scss/_drop_down.scss +185 -0
  24. package/scss/_menu_button.scss +151 -0
  25. package/scss/_root.scss +22 -0
  26. package/scss/_theme.scss +5 -0
  27. package/scss/_variables.scss +9 -0
  28. package/scss/_view_stack.scss +29 -0
  29. package/scss/_view_switcher_bar.scss +94 -0
  30. package/scss/adwaita-skin.scss +7 -0
  31. package/src/adw-data-grid.spec.ts +243 -0
  32. package/src/adw-dialog.spec.ts +169 -0
  33. package/src/adw-drop-down.spec.ts +186 -0
  34. package/src/elements/adw-data-grid.ts +335 -0
  35. package/src/elements/adw-dialog.ts +329 -0
  36. package/src/elements/adw-drop-down.ts +405 -0
  37. package/src/elements/adw-menu-button.ts +247 -0
  38. package/src/elements/adw-view-stack.ts +174 -0
  39. package/src/elements/adw-view-switcher-bar.ts +168 -0
  40. package/src/index.ts +16 -0
  41. package/src/source-view/adw-source-view.ts +436 -0
  42. package/src/source-view/asm6502.ts +232 -0
  43. package/src/source-view/hex.ts +43 -0
  44. package/src/source-view/index.ts +28 -0
  45. package/src/source-view/theme.ts +224 -0
  46. package/src/test.browser.mts +14 -0
  47. package/src/index.js +0 -1
  48. package/src/styles.generated.js +0 -2976
  49. package/src/styles2.generated.js +0 -2976
@@ -0,0 +1,43 @@
1
+ // Pure, framework-free helpers for <adw-source-view>. They carry no CodeMirror
2
+ // or DOM dependency so they stay unit-testable on any runtime and drive the
3
+ // gutter formatter + the hex copy-without-spaces behaviour.
4
+ // Reference: packages/app-gnome/src/gutter-renderer-line-numbers.ts (native parity)
5
+ // Reference: packages/app-gnome/src/widgets/source-view.ts onCopyHexClipboard()
6
+
7
+ /** Bytes represented per visual line in the hex monitor / hexdump gutter. */
8
+ export const HEX_ADDRESS_STRIDE = 16;
9
+
10
+ /**
11
+ * Format a 1-based CodeMirror line number as a 4-digit uppercase hex address,
12
+ * the way the native GtkSourceView hex gutter renders monitor/hexdump rows:
13
+ * each row advances the address by `stride` bytes from `start`.
14
+ *
15
+ * @param lineNo 1-based line number (CodeMirror's `formatNumber` contract).
16
+ * @param start base address of the first row (e.g. 0x0600 for a 6502 program).
17
+ * @param stride bytes per row (default 16 — one hexdump row).
18
+ */
19
+ export function formatHexAddress(lineNo: number, start: number, stride: number = HEX_ADDRESS_STRIDE): string {
20
+ const address = start + (lineNo - 1) * stride;
21
+ return address.toString(16).padStart(4, '0').toUpperCase();
22
+ }
23
+
24
+ /**
25
+ * Format a 1-based CodeMirror line number for the normal (decimal) gutter,
26
+ * offset by `start` so a pane can begin numbering at an arbitrary value —
27
+ * the web twin of the native renderer's `line + startValue`.
28
+ *
29
+ * @param lineNo 1-based line number.
30
+ * @param start value shown on the first line (default 1 → identity).
31
+ */
32
+ export function formatLineNumber(lineNo: number, start: number = 1): string {
33
+ return String(lineNo - 1 + start);
34
+ }
35
+
36
+ /**
37
+ * Strip every whitespace character from `text` — the copy-without-spaces
38
+ * transform the native hex monitor applies so a copied address/byte run pastes
39
+ * as a compact hex string. Mirrors `text.replace(/\s/g, '')` in the GTK widget.
40
+ */
41
+ export function stripWhitespace(text: string): string {
42
+ return text.replace(/\s/g, '');
43
+ }
@@ -0,0 +1,28 @@
1
+ // @gjsify/adwaita-web/source-view — opt-in entry for the CodeMirror-backed
2
+ // <adw-source-view> editor. Importing this module registers the custom element
3
+ // and self-injects its stylesheet. It is intentionally NOT re-exported from the
4
+ // package's main entry so CodeMirror stays out of the core adwaita-web bundle
5
+ // for consumers who do not need an editor.
6
+
7
+ export { AdwSourceView } from './adw-source-view.js';
8
+
9
+ // Building blocks, exported so apps/tests can reuse them (e.g. embed the 6502
10
+ // mode or the Adwaita theme in a bespoke EditorView).
11
+ export {
12
+ asm6502,
13
+ asm6502Parser,
14
+ asm6502TokenTable,
15
+ classifyWord,
16
+ token6502,
17
+ OPCODES,
18
+ REGISTERS,
19
+ DIRECTIVE_WORDS,
20
+ } from './asm6502.js';
21
+ export {
22
+ adwaitaEditorTheme,
23
+ adwaitaHighlightStyle,
24
+ ensureSourceViewStyleInjected,
25
+ SOURCE_VIEW_CSS,
26
+ SOURCE_VIEW_STYLE_ID,
27
+ } from './theme.js';
28
+ export { formatHexAddress, formatLineNumber, stripWhitespace, HEX_ADDRESS_STRIDE } from './hex.js';
@@ -0,0 +1,224 @@
1
+ // The Adwaita CodeMirror theme + syntax-highlight style for <adw-source-view>,
2
+ // plus the self-injected "chrome" stylesheet (container + copy button + the
3
+ // light/dark syntax palette variables).
4
+ //
5
+ // Editor colours are expressed as adwaita-web CSS custom properties
6
+ // (`--view-bg-color`, `--view-fg-color`, `--accent-color`, `--separator-color`)
7
+ // and a small `--adw-src-*` syntax palette defined below. Because those
8
+ // variables flip with the page theme (`.theme-dark` / `prefers-color-scheme`),
9
+ // a SINGLE theme + highlight style covers light and dark automatically — no
10
+ // per-scheme rebuild, mirroring the native widget's two GtkSourceView schemes.
11
+ // Reference: packages/app-gnome/src/widgets/source-view.ts updateStyle()
12
+ // Reference: refs/libadwaita/src/stylesheet (colour tokens)
13
+
14
+ import { EditorView } from '@codemirror/view';
15
+ import { HighlightStyle } from '@codemirror/language';
16
+ import { tags } from '@lezer/highlight';
17
+
18
+ /** Monospace stack — Adwaita Mono when present, else a portable code font. */
19
+ const MONO_FONT =
20
+ "'Adwaita Mono', 'Cascadia Code', 'JetBrains Mono', 'Source Code Pro', ui-monospace, 'SF Mono', Menlo, Consolas, monospace";
21
+
22
+ /** The CodeMirror EditorView theme mapping `.cm-*` chrome to Adwaita tokens. */
23
+ export const adwaitaEditorTheme = EditorView.theme({
24
+ '&': {
25
+ color: 'var(--view-fg-color, rgba(0,0,6,0.8))',
26
+ backgroundColor: 'var(--view-bg-color, #ffffff)',
27
+ fontSize: 'var(--adw-src-font-size, 10.5pt)',
28
+ },
29
+ '.cm-scroller': {
30
+ fontFamily: MONO_FONT,
31
+ lineHeight: '1.5',
32
+ },
33
+ '.cm-content': {
34
+ caretColor: 'var(--accent-color, #1c71d8)',
35
+ padding: '8px 0',
36
+ },
37
+ '.cm-cursor, .cm-dropCursor': {
38
+ borderLeftColor: 'var(--accent-color, #1c71d8)',
39
+ },
40
+ '.cm-selectionBackground, .cm-content ::selection': {
41
+ backgroundColor: 'var(--adw-src-selection)',
42
+ },
43
+ '&.cm-focused .cm-selectionBackground': {
44
+ backgroundColor: 'var(--adw-src-selection)',
45
+ },
46
+ '.cm-gutters': {
47
+ backgroundColor: 'var(--adw-src-gutter-bg, var(--view-bg-color, #ffffff))',
48
+ color: 'var(--adw-src-gutter-fg)',
49
+ border: 'none',
50
+ borderRight: '1px solid var(--separator-color, rgba(0,0,6,0.1))',
51
+ },
52
+ '.cm-lineNumbers .cm-gutterElement': {
53
+ padding: '0 10px 0 8px',
54
+ // Hex addresses are inherently LTR; keep the gutter text left-anchored
55
+ // so it never mirrors under an RTL page.
56
+ textAlign: 'right',
57
+ },
58
+ '.cm-activeLine': {
59
+ backgroundColor: 'var(--adw-src-active-line)',
60
+ },
61
+ '.cm-activeLineGutter': {
62
+ backgroundColor: 'var(--adw-src-active-line)',
63
+ color: 'var(--view-fg-color, rgba(0,0,6,0.8))',
64
+ },
65
+ '.cm-foldPlaceholder': {
66
+ backgroundColor: 'var(--button-bg-color, rgba(0,0,6,0.08))',
67
+ border: 'none',
68
+ color: 'var(--view-fg-color, rgba(0,0,6,0.8))',
69
+ },
70
+ });
71
+
72
+ /** Syntax highlighting mapping tags → the `--adw-src-*` palette variables. */
73
+ export const adwaitaHighlightStyle = HighlightStyle.define([
74
+ { tag: tags.lineComment, color: 'var(--adw-src-comment)', fontStyle: 'italic' },
75
+ { tag: tags.comment, color: 'var(--adw-src-comment)', fontStyle: 'italic' },
76
+ { tag: tags.keyword, color: 'var(--adw-src-keyword)', fontWeight: '600' },
77
+ { tag: tags.number, color: 'var(--adw-src-number)' },
78
+ { tag: tags.string, color: 'var(--adw-src-string)' },
79
+ { tag: tags.labelName, color: 'var(--adw-src-label)', fontWeight: '600' },
80
+ { tag: tags.atom, color: 'var(--adw-src-register)' },
81
+ { tag: tags.meta, color: 'var(--adw-src-directive)' },
82
+ { tag: tags.operator, color: 'var(--adw-src-operator)' },
83
+ { tag: tags.variableName, color: 'var(--view-fg-color, rgba(0,0,6,0.8))' },
84
+ ]);
85
+
86
+ // The light-theme syntax palette + shared chrome. Dark values are supplied by
87
+ // the overrides block (same mechanism as adwaita-web's _theme.scss: auto via
88
+ // prefers-color-scheme, manual via .theme-dark / opt-out via .theme-light).
89
+ const DARK_TOKENS = `
90
+ --adw-src-comment: #9a9996;
91
+ --adw-src-keyword: #78aeed;
92
+ --adw-src-number: #ffa348;
93
+ --adw-src-string: #8ff0a4;
94
+ --adw-src-label: #dc8add;
95
+ --adw-src-register: #33d1c9;
96
+ --adw-src-directive: #f66151;
97
+ --adw-src-operator: rgba(255, 255, 255, 0.55);
98
+ --adw-src-gutter-fg: rgba(255, 255, 255, 0.35);
99
+ --adw-src-active-line: color-mix(in srgb, #ffffff 6%, transparent);`;
100
+
101
+ /** Element id of the injected stylesheet (idempotency guard). */
102
+ export const SOURCE_VIEW_STYLE_ID = 'adw-source-view-style';
103
+
104
+ /** The chrome stylesheet: container, copy button, LTR pin, syntax palette. */
105
+ export const SOURCE_VIEW_CSS = `
106
+ .adw-source-view {
107
+ --adw-src-comment: #5e5c64;
108
+ --adw-src-keyword: #1c71d8;
109
+ --adw-src-number: #c64600;
110
+ --adw-src-string: #26a269;
111
+ --adw-src-label: #813d9c;
112
+ --adw-src-register: #007e8a;
113
+ --adw-src-directive: #a51d2d;
114
+ --adw-src-operator: rgba(0, 0, 6, 0.55);
115
+ --adw-src-selection: color-mix(in srgb, var(--accent-bg-color, #3584e4) 26%, transparent);
116
+ --adw-src-gutter-bg: var(--view-bg-color, #ffffff);
117
+ --adw-src-gutter-fg: rgba(0, 0, 6, 0.35);
118
+ --adw-src-active-line: color-mix(in srgb, var(--view-fg-color, #00000a) 4%, transparent);
119
+
120
+ /* Source code is inherently LTR — pin the whole widget so the gutter,
121
+ scrollbar and copy button never mirror under an RTL page. */
122
+ direction: ltr;
123
+ position: relative;
124
+ display: block;
125
+ box-sizing: border-box;
126
+ overflow: hidden;
127
+ border-radius: var(--card-radius, 12px);
128
+ background-color: var(--view-bg-color, #ffffff);
129
+ color: var(--view-fg-color, rgba(0, 0, 6, 0.8));
130
+ }
131
+
132
+ .adw-source-view .cm-editor {
133
+ border-radius: inherit;
134
+ max-height: 100%;
135
+ }
136
+
137
+ .adw-source-view.adw-source-view--fill,
138
+ .adw-source-view.adw-source-view--fill .cm-editor {
139
+ height: 100%;
140
+ }
141
+
142
+ .adw-source-view .cm-editor.cm-focused {
143
+ outline: none;
144
+ }
145
+
146
+ .adw-source-view__copy {
147
+ position: absolute;
148
+ top: 6px;
149
+ right: 6px;
150
+ z-index: 2;
151
+ display: inline-flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ width: 30px;
155
+ height: 30px;
156
+ padding: 0;
157
+ border: none;
158
+ border-radius: var(--button-radius, 9px);
159
+ background-color: color-mix(in srgb, var(--view-bg-color, #ffffff) 82%, transparent);
160
+ color: var(--view-fg-color, rgba(0, 0, 6, 0.75));
161
+ opacity: 0.72;
162
+ cursor: pointer;
163
+ transition: opacity 0.15s ease, background-color 0.15s ease;
164
+ -webkit-backdrop-filter: blur(6px);
165
+ backdrop-filter: blur(6px);
166
+ }
167
+
168
+ .adw-source-view__copy:hover {
169
+ opacity: 1;
170
+ background-color: var(--button-hover-color, rgba(0, 0, 6, 0.13));
171
+ }
172
+
173
+ .adw-source-view__copy:active {
174
+ background-color: var(--button-active-color, rgba(0, 0, 6, 0.19));
175
+ }
176
+
177
+ .adw-source-view__copy:focus-visible {
178
+ opacity: 1;
179
+ outline: 2px solid var(--accent-color, #1c71d8);
180
+ outline-offset: 1px;
181
+ }
182
+
183
+ .adw-source-view__copy[hidden] {
184
+ display: none;
185
+ }
186
+
187
+ .adw-source-view__copy svg {
188
+ width: 16px;
189
+ height: 16px;
190
+ display: block;
191
+ }
192
+
193
+ .adw-source-view__copy .adw-icon {
194
+ width: 16px;
195
+ height: 16px;
196
+ background-color: currentColor;
197
+ -webkit-mask-repeat: no-repeat;
198
+ mask-repeat: no-repeat;
199
+ -webkit-mask-position: center;
200
+ mask-position: center;
201
+ }
202
+
203
+ @media (prefers-color-scheme: dark) {
204
+ :root:not(.theme-light) .adw-source-view {${DARK_TOKENS}
205
+ }
206
+ }
207
+
208
+ :root.theme-dark .adw-source-view {${DARK_TOKENS}
209
+ }
210
+ `;
211
+
212
+ /**
213
+ * Inject the chrome stylesheet once (browser-only, idempotent). Matches the
214
+ * self-injection pattern of `@gjsify/adwaita-web`'s main entry, so importing
215
+ * the source-view subpath is enough to style it under any bundler.
216
+ */
217
+ export function ensureSourceViewStyleInjected(): void {
218
+ if (typeof document === 'undefined') return;
219
+ if (document.getElementById(SOURCE_VIEW_STYLE_ID)) return;
220
+ const style = document.createElement('style');
221
+ style.id = SOURCE_VIEW_STYLE_ID;
222
+ style.textContent = SOURCE_VIEW_CSS;
223
+ document.head.appendChild(style);
224
+ }
@@ -0,0 +1,14 @@
1
+ // Browser test entry for @gjsify/adwaita-web. Importing the package root
2
+ // registers every custom element AND self-applies the stylesheet, so the specs
3
+ // only have to create + drive the elements. Discovered + run by the
4
+ // tests/browser Playwright harness (see AGENTS.md → Browser tests).
5
+ import { run } from '@gjsify/unit';
6
+
7
+ // Registers the custom elements (side-effect) + injects the compiled CSS.
8
+ import '@gjsify/adwaita-web';
9
+
10
+ import { AdwDataGridTest } from './adw-data-grid.spec.js';
11
+ import { AdwDialogTest } from './adw-dialog.spec.js';
12
+ import { AdwDropDownTest } from './adw-drop-down.spec.js';
13
+
14
+ run({ AdwDataGridTest, AdwDialogTest, AdwDropDownTest });
package/src/index.js DELETED
@@ -1 +0,0 @@
1
- import{e}from"./styles2.generated.js";import{AdwAvatar as t}from"./elements/adw-avatar2.js";import{AdwBanner as n}from"./elements/adw-banner2.js";import{AdwCard as r}from"./elements/adw-card2.js";import{AdwClamp as i}from"./elements/adw-clamp2.js";import{AdwSpinner as a}from"./elements/adw-spinner2.js";import{AdwStatusPage as o}from"./elements/adw-status-page2.js";import{AdwWindow as s}from"./elements/adw-window2.js";import{AdwHeaderBar as c}from"./elements/adw-header-bar2.js";import{AdwWindowTitle as l}from"./elements/adw-window-title2.js";import{AdwButton as u}from"./elements/adw-button2.js";import{AdwButtonContent as d}from"./elements/adw-button-content2.js";import{AdwSplitButton as f}from"./elements/adw-split-button2.js";import{AdwToggle as p,AdwToggleGroup as m}from"./elements/adw-toggle-group2.js";import{AdwEntry as h}from"./elements/adw-entry2.js";import{AdwPreferencesGroup as g}from"./elements/adw-preferences-group2.js";import{AdwActionRow as _}from"./elements/adw-action-row2.js";import{AdwEntryRow as v}from"./elements/adw-entry-row2.js";import{AdwSwitchRow as y}from"./elements/adw-switch-row2.js";import{AdwComboRow as b}from"./elements/adw-combo-row2.js";import{AdwSpinRow as x}from"./elements/adw-spin-row2.js";import{AdwButtonRow as S}from"./elements/adw-button-row2.js";import{AdwExpanderRow as C}from"./elements/adw-expander-row2.js";import{AdwPasswordEntryRow as w}from"./elements/adw-password-entry-row2.js";import{AdwToastOverlay as T}from"./elements/adw-toast-overlay2.js";import{AdwToolbarView as E}from"./elements/adw-toolbar-view2.js";import{AdwWrapBox as D}from"./elements/adw-wrap-box2.js";import{AdwOverlaySplitView as O}from"./elements/adw-overlay-split-view2.js";import{AdwNavigationSplitView as k}from"./elements/adw-navigation-split-view2.js";import{AdwCarousel as A,AdwCarouselIndicatorDots as j,AdwCarouselIndicatorLines as M}from"./elements/adw-carousel2.js";import{AdwTabPage as N,AdwTabView as P}from"./elements/adw-tab-view2.js";import{AdwViewSwitcher as F,AdwViewSwitcherPage as I}from"./elements/adw-view-switcher2.js";import{AdwInlineViewSwitcher as L,AdwViewStackPage as R}from"./elements/adw-inline-view-switcher2.js";import{AdwNavigationPage as z,AdwNavigationView as B}from"./elements/adw-navigation-view2.js";import{AdwBottomSheet as V,AdwBottomSheetContent as H,AdwBottomSheetSheet as U}from"./elements/adw-bottom-sheet2.js";import{AdwSidebar as W,AdwSidebarItem as G,AdwSidebarSection as K}from"./elements/adw-sidebar2.js";import{AdwAboutDialog as q}from"./elements/adw-about-dialog2.js";import{AdwAlertDialog as J,AdwAlertResponse as Y}from"./elements/adw-alert-dialog2.js";import{AdwPreferencesDialog as X,AdwPreferencesPage as Z}from"./elements/adw-preferences-dialog2.js";import"@gjsify/adwaita-fonts";if(typeof document<`u`&&!document.getElementById(`adwaita-web-style`)){let t=document.createElement(`style`);t.id=`adwaita-web-style`,t.textContent=e,document.head.appendChild(t)}export{q as AdwAboutDialog,_ as AdwActionRow,J as AdwAlertDialog,Y as AdwAlertResponse,t as AdwAvatar,n as AdwBanner,V as AdwBottomSheet,H as AdwBottomSheetContent,U as AdwBottomSheetSheet,u as AdwButton,d as AdwButtonContent,S as AdwButtonRow,r as AdwCard,A as AdwCarousel,j as AdwCarouselIndicatorDots,M as AdwCarouselIndicatorLines,i as AdwClamp,b as AdwComboRow,h as AdwEntry,v as AdwEntryRow,C as AdwExpanderRow,c as AdwHeaderBar,L as AdwInlineViewSwitcher,z as AdwNavigationPage,k as AdwNavigationSplitView,B as AdwNavigationView,O as AdwOverlaySplitView,w as AdwPasswordEntryRow,X as AdwPreferencesDialog,g as AdwPreferencesGroup,Z as AdwPreferencesPage,W as AdwSidebar,G as AdwSidebarItem,K as AdwSidebarSection,x as AdwSpinRow,a as AdwSpinner,f as AdwSplitButton,o as AdwStatusPage,y as AdwSwitchRow,N as AdwTabPage,P as AdwTabView,T as AdwToastOverlay,p as AdwToggle,m as AdwToggleGroup,E as AdwToolbarView,R as AdwViewStackPage,F as AdwViewSwitcher,I as AdwViewSwitcherPage,s as AdwWindow,l as AdwWindowTitle,D as AdwWrapBox};