sol-components 2.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.
Files changed (150) hide show
  1. package/README.md +7 -0
  2. package/core/activate.js +27 -0
  3. package/core/adopt.js +71 -0
  4. package/core/auth-core.js +73 -0
  5. package/core/auth-fetch.js +154 -0
  6. package/core/component-mount.js +110 -0
  7. package/core/defaults.js +48 -0
  8. package/core/define.js +15 -0
  9. package/core/display-target.js +166 -0
  10. package/core/edit-placements.js +28 -0
  11. package/core/editor-self.js +127 -0
  12. package/core/editor.js +162 -0
  13. package/core/events.js +27 -0
  14. package/core/extension-points.js +189 -0
  15. package/core/form-utils.js +210 -0
  16. package/core/from-query.js +138 -0
  17. package/core/from-rdf.js +52 -0
  18. package/core/here.js +33 -0
  19. package/core/include-core.js +73 -0
  20. package/core/inrupt-global.js +18 -0
  21. package/core/menu-consumer.js +41 -0
  22. package/core/menu-rdf.js +154 -0
  23. package/core/pod-ops.js +392 -0
  24. package/core/pod-registry.js +82 -0
  25. package/core/popup-proxy.js +255 -0
  26. package/core/rdf-core.js +280 -0
  27. package/core/rdf-render.js +136 -0
  28. package/core/rdf-utils.js +411 -0
  29. package/core/rdf.js +154 -0
  30. package/core/services.js +106 -0
  31. package/core/shape-to-form.js +741 -0
  32. package/core/sparql-safety.js +20 -0
  33. package/core/utils.js +196 -0
  34. package/dist/importmap-cdn.json +49 -0
  35. package/dist/importmap-local.json +49 -0
  36. package/dist/sol-loader.manifest.json +140 -0
  37. package/dist/vendor/@comunica-query-sparql.js +137851 -0
  38. package/dist/vendor/@inrupt-solid-client-authn-browser.js +7503 -0
  39. package/dist/vendor/dompurify.js +1476 -0
  40. package/dist/vendor/ical.js.js +9739 -0
  41. package/dist/vendor/marked.js +85 -0
  42. package/dist/vendor/n3.js +14670 -0
  43. package/dist/vendor/rdf-validate-shacl.js +6970 -0
  44. package/dist/vendor/rdflib.js +35172 -0
  45. package/dist/vendor/solid-logic.js +6819 -0
  46. package/dist/vendor/solid-ui.js +21945 -0
  47. package/node/sol-form.js +133 -0
  48. package/node/sol-include.js +55 -0
  49. package/node/sol-login.js +632 -0
  50. package/node/sol-menu.js +639 -0
  51. package/node/sol-query.js +116 -0
  52. package/package.json +133 -0
  53. package/web/menu-from-rdf.js +23 -0
  54. package/web/scripts/prefs.js +25 -0
  55. package/web/sol-accordion.js +114 -0
  56. package/web/sol-basic.js +50 -0
  57. package/web/sol-breadcrumb.js +131 -0
  58. package/web/sol-button.js +244 -0
  59. package/web/sol-calendar.js +465 -0
  60. package/web/sol-default.js +118 -0
  61. package/web/sol-dropdown-button.js +222 -0
  62. package/web/sol-feed.js +1336 -0
  63. package/web/sol-form.js +949 -0
  64. package/web/sol-full.js +43 -0
  65. package/web/sol-gallery.js +303 -0
  66. package/web/sol-include.js +246 -0
  67. package/web/sol-live-edit.js +415 -0
  68. package/web/sol-login.js +856 -0
  69. package/web/sol-menu.js +593 -0
  70. package/web/sol-modal.js +377 -0
  71. package/web/sol-pod-extras.js +17 -0
  72. package/web/sol-pod-ops.js +680 -0
  73. package/web/sol-pod.js +1039 -0
  74. package/web/sol-query.js +546 -0
  75. package/web/sol-rolodex.js +95 -0
  76. package/web/sol-search.js +402 -0
  77. package/web/sol-settings.js +199 -0
  78. package/web/sol-solidos.js +93 -0
  79. package/web/sol-tabs.js +445 -0
  80. package/web/sol-time.js +194 -0
  81. package/web/sol-tree-edit.js +492 -0
  82. package/web/sol-wac.js +456 -0
  83. package/web/sol-weather.js +337 -0
  84. package/web/sol-window.js +142 -0
  85. package/web/styles/buttons-css.js +108 -0
  86. package/web/styles/help.css +242 -0
  87. package/web/styles/root.css +112 -0
  88. package/web/styles/sol-accordion-css.js +97 -0
  89. package/web/styles/sol-calendar-css.js +154 -0
  90. package/web/styles/sol-feed-css.js +475 -0
  91. package/web/styles/sol-form-css.js +471 -0
  92. package/web/styles/sol-gallery-css.js +181 -0
  93. package/web/styles/sol-include-css.js +95 -0
  94. package/web/styles/sol-live-edit-css.js +84 -0
  95. package/web/styles/sol-live-edit.css +101 -0
  96. package/web/styles/sol-login-css.js +116 -0
  97. package/web/styles/sol-menu-css.js +145 -0
  98. package/web/styles/sol-modal-css.js +134 -0
  99. package/web/styles/sol-pod-css.js +187 -0
  100. package/web/styles/sol-pod-modal-css.js +203 -0
  101. package/web/styles/sol-query-css.js +140 -0
  102. package/web/styles/sol-query-help.css +267 -0
  103. package/web/styles/sol-query-one-pager.css +67 -0
  104. package/web/styles/sol-search-css.js +157 -0
  105. package/web/styles/sol-solidos-css.js +7 -0
  106. package/web/styles/sol-tabs-css.js +114 -0
  107. package/web/styles/sol-time-css.js +30 -0
  108. package/web/styles/sol-wac-css.js +73 -0
  109. package/web/styles/sol-weather-css.js +59 -0
  110. package/web/styles/solid-logo.svg +9 -0
  111. package/web/styles/view-accordion-css.js +66 -0
  112. package/web/styles/view-anchorlist-css.js +22 -0
  113. package/web/styles/view-autocomplete-css.js +59 -0
  114. package/web/styles/view-rolodex-css.js +102 -0
  115. package/web/styles/view-select-css.js +21 -0
  116. package/web/utils/calendar-fetch.js +388 -0
  117. package/web/utils/code-mirror-editor.js +82 -0
  118. package/web/utils/commons-fetch.js +108 -0
  119. package/web/utils/feed-edit.js +159 -0
  120. package/web/utils/feed-edit.smoke.mjs +74 -0
  121. package/web/utils/feed-fetch.js +573 -0
  122. package/web/utils/live-edit-help/csv.js +64 -0
  123. package/web/utils/live-edit-help/graphviz.js +41 -0
  124. package/web/utils/live-edit-help/jsonld.js +55 -0
  125. package/web/utils/live-edit-help/markdown.js +52 -0
  126. package/web/utils/live-edit-help/mermaid.js +48 -0
  127. package/web/utils/live-edit-help/turtle.js +85 -0
  128. package/web/utils/rdf-config.js +125 -0
  129. package/web/utils/renderers/csv.js +124 -0
  130. package/web/utils/renderers/d3-force.js +82 -0
  131. package/web/utils/renderers/graphviz.js +13 -0
  132. package/web/utils/renderers/html.js +10 -0
  133. package/web/utils/renderers/jsonld.js +63 -0
  134. package/web/utils/renderers/markdown.js +19 -0
  135. package/web/utils/renderers/mermaid.js +54 -0
  136. package/web/utils/renderers/turtle.js +51 -0
  137. package/web/utils/sol-query-triple-patterns.js +151 -0
  138. package/web/utils/sol-query-ui.js +250 -0
  139. package/web/utils/sol-query-views.js +32 -0
  140. package/web/views/_helpers.js +34 -0
  141. package/web/views/accordion.js +133 -0
  142. package/web/views/anchorlist.js +59 -0
  143. package/web/views/auto-complete.js +183 -0
  144. package/web/views/dl.js +38 -0
  145. package/web/views/list.js +19 -0
  146. package/web/views/menu.js +56 -0
  147. package/web/views/rolodex.js +126 -0
  148. package/web/views/select.js +79 -0
  149. package/web/views/table.js +73 -0
  150. package/web/views/tabs.js +57 -0
@@ -0,0 +1,95 @@
1
+ import { sheetFrom } from '../../core/adopt.js';
2
+
3
+ export const CSS = `
4
+ :host {
5
+ /* flex column so sol-include propagates a definite height from a
6
+ flex parent (sol-menu's content area, dk's app-shell, etc.)
7
+ down to its slotted content — components placed inside (sol-pod,
8
+ sol-menu, etc.) can then fill and scroll on their own. In a
9
+ block-flow parent this still behaves like a block-level box,
10
+ just with flex internals — no visible change. */
11
+ display: flex;
12
+ flex-direction: column;
13
+ flex: 1 1 auto;
14
+ min-height: 0;
15
+ color: var(--text, #212121);
16
+ font-family: var(--font-ui, system-ui, sans-serif);
17
+ font-size: var(--font-size, var(--medium-font, 20px));
18
+ }
19
+ /* The .si-content wrapper. In untrusted mode it's a shadow-DOM
20
+ child of sol-include; in trusted mode it's a slotted light-DOM
21
+ child. Style both forms — the bare selector matches in shadow,
22
+ ::slotted reaches it through the <slot>. Without this rule for
23
+ the slotted case, page content inside (e.g. sol-pod via help
24
+ demos) loses its height anchor and collapses to zero. */
25
+ .si-content,
26
+ ::slotted(.si-content) {
27
+ display: flex;
28
+ flex-direction: column;
29
+ flex: 1 1 auto;
30
+ min-height: 0;
31
+ }
32
+ .si-raw {
33
+ white-space: pre-wrap;
34
+ font-family: var(--font-mono, monospace);
35
+ font-size: var(--small-font, 16px);
36
+ background: var(--code-bg, #f4f4f4);
37
+ color: var(--text, #212121);
38
+ padding: var(--space-xl, 16px);
39
+ border-radius: var(--radius-sm, 4px);
40
+ overflow-x: auto;
41
+ }
42
+ .si-loading { color: var(--text-muted, #666); padding: var(--space-lg, 12px); font-style: italic; }
43
+ .si-empty { color: var(--text-muted, #888); padding: var(--space-lg, 12px); font-style: italic; }
44
+ .si-error {
45
+ color: var(--error, #c00);
46
+ padding: var(--space-lg, 12px) var(--space-xl, 16px);
47
+ background: color-mix(in srgb, var(--error, #e74c3c) 12%, transparent);
48
+ border: 1px solid var(--error, #fcc);
49
+ border-radius: var(--radius-sm, 4px);
50
+ }
51
+
52
+ .si-content h1, .si-content h2, .si-content h3,
53
+ .si-content h4, .si-content h5, .si-content h6 {
54
+ margin: 1.1em 0 .4em; line-height: var(--line-height-tight, 1.25);
55
+ }
56
+ .si-content p { margin: 0 0 .75em; }
57
+ .si-content ul, .si-content ol { margin: 0 0 .75em 1.5em; }
58
+ .si-content li { margin: .2em 0; }
59
+ .si-content pre {
60
+ background: var(--include-code-bg, var(--code-bg, #f4f4f4));
61
+ padding: var(--include-pre-padding, var(--space-lg, 12px));
62
+ border-radius: var(--radius-sm, 4px);
63
+ overflow-x: auto;
64
+ }
65
+ .si-content code {
66
+ background: var(--include-code-bg, var(--code-bg, #f0f0f0));
67
+ padding: var(--include-code-padding, .1em .3em);
68
+ border-radius: var(--radius-sm, 4px);
69
+ font-size: var(--small-font, 16px);
70
+ font-family: var(--font-mono, monospace);
71
+ }
72
+ .si-content pre code { background: none; padding: 0; }
73
+ .si-content blockquote {
74
+ border-left: 3px solid var(--include-blockquote-border, var(--border, #ccc));
75
+ margin: 0 0 .75em 0;
76
+ padding: .25em 1em;
77
+ color: var(--include-blockquote-color, var(--text-muted, #555));
78
+ }
79
+ .si-content a { color: var(--accent, #0066cc); }
80
+ .si-content a:hover { text-decoration: underline; }
81
+ .si-content a:focus-visible {
82
+ outline: 2px solid var(--accent, #4a9eff);
83
+ outline-offset: 2px;
84
+ }
85
+ .si-content img { max-width: 100%; }
86
+ .si-content table { border-collapse: collapse; margin-bottom: .75em; }
87
+ .si-content th, .si-content td {
88
+ border: 1px solid var(--border, #ddd);
89
+ padding: .3em .6em;
90
+ }
91
+ .si-content th { background: var(--hover, #f5f5f5); }
92
+ `;
93
+
94
+ export const sheet = sheetFrom(CSS);
95
+ export default sheet;
@@ -0,0 +1,84 @@
1
+ // Styles for <sol-live-edit> shadow DOM.
2
+ // Uses CSS custom properties so the host page's theme (podz or standalone)
3
+ // flows through.
4
+ import { sheetFrom } from '../../core/adopt.js';
5
+
6
+ export const CSS = `
7
+ :host{display:flex;flex-direction:column;overflow:hidden;font-family:inherit;position:relative}
8
+ .er{padding:.5em 1em;background:#fff0f0;border-bottom:1px solid #f5c6cb;color:#c0392b;font-size:.82em;display:none;flex-shrink:0}
9
+ .er.on{display:block}
10
+
11
+ .cf{display:none;position:absolute;top:34px;right:0;z-index:20;
12
+ min-width:180px;padding:10px 14px;
13
+ background:var(--surface,#fff);border:1px solid var(--border,#ccc);
14
+ border-radius:0 0 0 8px;box-shadow:0 4px 16px rgba(0,0,0,.15);
15
+ flex-direction:column;gap:10px;font-size:.82em}
16
+ .cf.on{display:flex}
17
+ .cg{display:flex;flex-direction:column;gap:4px}
18
+ .cg b{font-weight:700;color:var(--text,#333);margin-bottom:2px;font-size:.9em}
19
+ .cg label{display:flex;align-items:center;gap:6px;cursor:pointer;color:var(--text,#222);padding:1px 0}
20
+ .cg input[type=radio]{margin:0;cursor:pointer;accent-color:var(--accent,#4a9eff)}
21
+
22
+ .modal-backdrop{display:none;position:absolute;inset:0;z-index:30;
23
+ background:rgba(0,0,0,.35);align-items:center;justify-content:center}
24
+ .modal-backdrop.on{display:flex}
25
+ .modal-box{background:var(--surface,#fff);border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,.25);
26
+ max-width:90%;max-height:85%;width:600px;overflow-y:auto;position:relative;padding:1.2rem 1.5rem 1.5rem}
27
+ .modal-box.wide{width:800px}
28
+ .modal-close{position:absolute;top:8px;right:12px;border:none;background:none;
29
+ font-size:1.3em;cursor:pointer;color:var(--text-muted,#888);line-height:1;padding:4px}
30
+ .modal-close:hover{color:var(--text,#333)}
31
+
32
+ .modal-box h2{margin:.2em 0 .7em;font-size:1.05em}
33
+ .modal-box h3{margin:.9em 0 .25em;font-size:.92em;color:var(--accent,#4a9eff)}
34
+ .modal-box h4{margin:.5em 0 .12em;font-size:.86em}
35
+ .modal-box p{margin:.15em 0 .4em;font-size:.84em;color:var(--text-muted,#555)}
36
+ .modal-box code{display:block;white-space:pre;overflow-x:auto;font-size:.8em;
37
+ background:var(--code-bg,#f4f4f4);padding:.4em .7em;border-radius:4px;
38
+ border:1px solid var(--border,#ddd);margin:.15em 0 .5em}
39
+
40
+ .modal-box .sc{display:inline-block;vertical-align:top;margin:.4rem;padding:.4rem .7rem;
41
+ border:1px solid var(--border,#ddd);border-radius:6px}
42
+ .modal-box .sc h3{margin:0 0 .25em;font-size:.86em}
43
+ .modal-box .stat-table td{padding:2px 8px;font-size:.8em}
44
+
45
+ .body{display:flex;flex:1;overflow:hidden}
46
+ .ep{flex:1;display:flex;flex-direction:column;overflow:hidden}
47
+ .pp{flex:1;overflow:auto;position:relative;display:flex;justify-content:safe center;align-items:safe center}
48
+
49
+ /* Resizer — draggable divider between the editor and preview panes. */
50
+ .sle-resizer{flex:0 0 6px;align-self:stretch;cursor:col-resize;
51
+ background:var(--border,#ccc);touch-action:none}
52
+ .sle-resizer:hover,.sle-resizer.dragging{background:var(--accent,#4a9eff)}
53
+ .pp>#po{flex-shrink:0}
54
+ .pp .sle-md-preview{padding:1rem}
55
+
56
+ .csv-tbl{width:100%;border-collapse:collapse;font-size:.88em}
57
+ .csv-tbl th{padding:7px 10px;text-align:left;background:var(--text,#222);color:var(--surface,#fff);font-weight:600;position:sticky;top:0;z-index:1}
58
+ .csv-tbl td{padding:5px 10px;border-bottom:1px solid var(--border,#eee)}
59
+ .csv-tbl tr:nth-child(even) td{background:var(--hover,#f4f4f4)}
60
+
61
+ /* Toolbar — Save / Settings / Help / Zoom / Statistics, right-aligned. */
62
+ .sle-toolbar{display:flex;align-items:center;justify-content:flex-end;gap:6px;
63
+ flex-shrink:0;padding:4px 8px;border-bottom:1px solid var(--border,#ccc);
64
+ background:var(--surface,#fff)}
65
+ .sle-btn{border:1px solid var(--border,#ccc);background:var(--surface,#fff);
66
+ color:var(--text,#333);cursor:pointer;font:inherit;font-size:.82em;
67
+ padding:3px 10px;border-radius:5px;line-height:1.5}
68
+ .sle-btn:hover{background:var(--hover,#f0f0f0)}
69
+ .sle-btn[hidden]{display:none}
70
+ .sle-btn-primary{background:var(--accent,#4a9eff);border-color:var(--accent,#4a9eff);color:#fff}
71
+ .sle-btn-primary:hover{background:var(--accent,#4a9eff);filter:brightness(1.08)}
72
+ /* Zoom control — sits in the toolbar; shown only for zoomable formats. */
73
+ .sle-zoom{display:flex;align-items:center;gap:2px}
74
+ .sle-zoom[hidden]{display:none}
75
+ .sle-zoom button{border:1px solid var(--border,#ccc);background:var(--surface,#fff);
76
+ cursor:pointer;color:var(--text,#333);font-size:1em;line-height:1;
77
+ padding:3px 9px;border-radius:5px}
78
+ .sle-zoom button:hover{background:var(--hover,#f0f0f0)}
79
+ .sle-zoom span{min-width:3.4em;text-align:center;color:var(--text-muted,#555);
80
+ font-size:.82em;font-variant-numeric:tabular-nums}
81
+ `;
82
+
83
+ export const sheet = sheetFrom(CSS);
84
+ export default sheet;
@@ -0,0 +1,101 @@
1
+ /* Live-editor standalone page styles.
2
+ Maps live-ed theme vars to the CSS var names that sol-live-edit (and podz) use. */
3
+
4
+ :root {
5
+ --bg: #f5f5f5;
6
+ --surface: #ffffff;
7
+ --border: #d0d0d0;
8
+ --text: #2c3e50;
9
+ --text-muted: #7f8c8d;
10
+ --accent: #3498db;
11
+ --accent-dark: #2980b9;
12
+ --hover: #eaf2fb;
13
+ --focus-bg: #ebf5fb;
14
+ --code-bg: #f4f4f4;
15
+ --error: #e74c3c;
16
+ --success: #27ae60;
17
+ --shadow: rgba(0,0,0,0.08);
18
+
19
+ --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
20
+ --font-mono: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
21
+ }
22
+
23
+ @media (prefers-color-scheme: dark) {
24
+ :root:not([data-theme="light"]) {
25
+ --bg: #1a1a1a;
26
+ --surface: #252525;
27
+ --border: #3e3e3e;
28
+ --text: #e0e0e0;
29
+ --text-muted: #909090;
30
+ --hover: #2e2e2e;
31
+ --focus-bg: #2a2e34;
32
+ --code-bg: #1e1e1e;
33
+ --accent: #4dabf7;
34
+ --accent-dark: #339af0;
35
+ }
36
+ }
37
+ [data-theme="dark"] {
38
+ --bg: #1a1a1a;
39
+ --surface: #252525;
40
+ --border: #3e3e3e;
41
+ --text: #e0e0e0;
42
+ --text-muted: #909090;
43
+ --hover: #2e2e2e;
44
+ --focus-bg: #2a2e34;
45
+ --code-bg: #1e1e1e;
46
+ --accent: #4dabf7;
47
+ --accent-dark: #339af0;
48
+ }
49
+
50
+ *, *::before, *::after { box-sizing: border-box; }
51
+
52
+ html, body {
53
+ margin: 0; padding: 0; height: 100%;
54
+ font-family: var(--font-ui);
55
+ background: var(--bg);
56
+ color: var(--text);
57
+ }
58
+
59
+ body { display: flex; flex-direction: column; }
60
+
61
+ header {
62
+ display: flex; align-items: center; gap: 10px;
63
+ padding: 8px 16px;
64
+ background: var(--surface);
65
+ border-bottom: 1px solid var(--border);
66
+ flex-shrink: 0;
67
+ }
68
+
69
+ header h1 { font-size: 1rem; font-weight: 600; margin: 0; flex: 1; }
70
+
71
+ /* Header buttons use .sol-btn .sol-btn-sm / .sol-btn-primary — see buttons-css.js. */
72
+ .sol-btn {
73
+ font: inherit;
74
+ background: var(--surface);
75
+ color: var(--text);
76
+ border: 1px solid var(--border);
77
+ border-radius: 4px;
78
+ padding: 0.35em 0.8em;
79
+ line-height: 1.2;
80
+ cursor: pointer;
81
+ white-space: nowrap;
82
+ box-sizing: border-box;
83
+ }
84
+ .sol-btn:hover { background: var(--hover); border-color: var(--accent); }
85
+ .sol-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
86
+ .sol-btn[disabled], .sol-btn:disabled { opacity: 0.55; cursor: not-allowed; }
87
+ .sol-btn-sm { padding: 3px 10px; font-size: 0.82em; }
88
+ .sol-btn-primary {
89
+ background: var(--accent); color: #fff; border-color: var(--accent);
90
+ }
91
+ .sol-btn-primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
92
+ .sol-btn-ghost {
93
+ background: transparent; border-color: transparent; color: var(--text-muted);
94
+ }
95
+ .sol-btn-ghost:hover { background: var(--hover); color: var(--text); border-color: transparent; }
96
+
97
+ .theme-toggle { font-size: 1.1em; padding: 3px 7px; }
98
+
99
+ sol-live-edit { flex: 1; overflow: hidden; min-height: 0; }
100
+
101
+ .hdr-zoom { font-size: 0.82em; color: var(--text-muted); min-width: 3em; text-align: center; }
@@ -0,0 +1,116 @@
1
+ import { sheetFrom } from '../../core/adopt.js';
2
+ import { BTN_CSS } from './buttons-css.js';
3
+
4
+ export const CSS = BTN_CSS + `
5
+ /* Hidden by default. Frames embed sol-login for the auth-needed
6
+ listener side-effect; the element surfaces UI only when an auth
7
+ prompt is actively in flight (host gains the 'active' attribute)
8
+ so callers do not need to allocate chrome space for a permanent
9
+ login chip. Hosts that DO want a permanent chip can override
10
+ with style="display: inline-flex". */
11
+ :host { display: none; }
12
+ :host([active]),
13
+ :host([visible]),
14
+ :host([external-auth]) {
15
+ display: inline-flex;
16
+ align-items: center;
17
+ gap: 8px;
18
+ font-family: system-ui, -apple-system, sans-serif;
19
+ /* Anchor to the theme font token so the button scales with it. */
20
+ font-size: var(--font-size, 20px);
21
+ }
22
+
23
+ /* Another same-origin window/tab/iframe holds a logged-in session
24
+ (signaled via BroadcastChannel('sol-auth')). Surface the chip and
25
+ paint the button green so the user can choose to also log in
26
+ here. Suppressed while this element's own auth flow is in flight
27
+ (host has [active]) — that UI takes precedence. */
28
+ :host([external-auth]:not([active])) .auth-btn {
29
+ box-shadow: 0 0 0 2px var(--success, #388e3c);
30
+ border-color: var(--success, #388e3c);
31
+ color: var(--success, #388e3c);
32
+ }
33
+
34
+ .auth-status {
35
+ font-size: 0.7em;
36
+ color: var(--text-muted, #666);
37
+ white-space: nowrap;
38
+ overflow: hidden;
39
+ text-overflow: ellipsis;
40
+ max-width: 220px;
41
+ }
42
+ .auth-status.logged-in { color: var(--success, #388e3c); }
43
+
44
+ /* Match the padding of the pod header controls (select / gear) it
45
+ sits between, so the row reads as one set of controls. */
46
+ .auth-btn { padding: 6px 10px; }
47
+
48
+ /* Logged in: the button turns green (green = connected). */
49
+ .auth-btn.logged-in {
50
+ background: var(--success, #388e3c);
51
+ border-color: var(--success, #388e3c);
52
+ color: #fff;
53
+ }
54
+ .auth-btn.logged-in:hover {
55
+ background: var(--success-dark, #2e7d32);
56
+ border-color: var(--success-dark, #2e7d32);
57
+ }
58
+
59
+ /* Login button uses .sol-btn .sol-btn-sm; .sol-btn-primary when logged out. */
60
+
61
+ .dropdown {
62
+ position: fixed; z-index: 9999;
63
+ background: var(--surface, #fff);
64
+ border: 1px solid var(--border, #e0e0e0);
65
+ border-radius: 6px;
66
+ box-shadow: 0 6px 18px var(--shadow, rgba(0,0,0,0.1));
67
+ padding: 8px;
68
+ /* Size to the widest issuer so every entry fits on one line; cap to
69
+ the viewport so it can't run off-screen. */
70
+ width: max-content;
71
+ min-width: 44ch; max-width: 90vw;
72
+ display: none;
73
+ }
74
+ .dropdown.open { display: block; }
75
+
76
+ /* Hint shown above the issuer list while auto-login is in flight.
77
+ Names the issuer being signed into and prompts the user to click
78
+ another option in the list to switch. Inserted/removed by
79
+ _showSwitchHint / _hideSwitchHint as part of the auth-needed
80
+ auto-login flow. */
81
+ .switch-hint {
82
+ font-size: 0.78em;
83
+ color: var(--text-muted, #4d4d4d);
84
+ padding: 2px 6px 6px 6px;
85
+ border-bottom: 1px solid var(--border-soft, #e5e5e5);
86
+ margin-bottom: 6px;
87
+ white-space: nowrap;
88
+ overflow: hidden;
89
+ text-overflow: ellipsis;
90
+ }
91
+
92
+ .issuer-list { display: flex; flex-direction: column; gap: 2px; margin-bottom: 8px; }
93
+ .issuer-list:empty { display: none; }
94
+
95
+ .issuer-item {
96
+ text-align: left; background: none; border: none;
97
+ padding: 5px 8px; border-radius: 4px;
98
+ cursor: pointer; font-size: 0.84em;
99
+ color: var(--text, #212121);
100
+ white-space: nowrap;
101
+ font-family: inherit;
102
+ }
103
+ .issuer-item:hover { background: var(--hover, #f0f0f0); color: var(--accent, #2196f3); }
104
+
105
+ .custom-row { display: flex; gap: 4px; }
106
+ .custom-row .sol-btn { padding: 6px 8px; font-size: 0.82em; }
107
+ .custom-row .issuer-input {
108
+ /* 44ch floor so a full issuer URL is visible; this also drives the
109
+ dropdown's max-content width, so the panel grows to fit it. */
110
+ flex: 1; min-width: 44ch; font-size: 0.82em; padding: 6px 8px;
111
+ background: var(--bg, #f5f5f5);
112
+ }
113
+ `;
114
+
115
+ export const sheet = sheetFrom(CSS);
116
+ export default sheet;
@@ -0,0 +1,145 @@
1
+ import { sheetFrom } from '../../core/adopt.js';
2
+
3
+ export const CSS = `
4
+ :host {
5
+ display: flex; flex-direction: row;
6
+ flex: 1; min-height: 0; min-width: 0;
7
+ max-width: 100%; height: 100%;
8
+ overflow: hidden;
9
+ box-sizing: border-box;
10
+ font-family:var(--font-ui) !important;
11
+ font-size: var(--font-size, var(--medium-font, 20px));
12
+ }
13
+ :host([orientation="horizontal"]) {
14
+ flex-direction: column;
15
+ }
16
+ .sol-menu-embed {
17
+ display: flex; flex-direction: column;
18
+ flex: 1; min-height: 0; min-width: 0;
19
+ width: 100%; max-width: 100%;
20
+ overflow: auto;
21
+ }
22
+
23
+ .sol-menu-nav {
24
+ display: flex; flex-direction: column;
25
+ flex-shrink: 0;
26
+ min-width: var(--menu-nav-min-width, 140px);
27
+ max-width: var(--menu-nav-max-width, 260px);
28
+ padding: var(--space-md, 8px);
29
+ gap: var(--space-xs, 2px);
30
+ border-right: 1px solid var(--border, #e0e0e0);
31
+ overflow-y: auto; overflow-x: hidden;
32
+ scrollbar-width: thin;
33
+ box-sizing: border-box;
34
+ }
35
+ :host([orientation="horizontal"]) > .sol-menu-nav {
36
+ flex-direction: row;
37
+ flex-wrap: wrap;
38
+ min-width: 0; max-width: 100%;
39
+ padding: var(--space-sm, 4px) var(--space-lg, 12px);
40
+ gap: var(--space-sm, 4px);
41
+ border-right: none;
42
+ border-bottom: var(--menu-nav-border-bottom, 1px solid var(--border, #e0e0e0));
43
+ /* No overflow scroll on the nav itself — when items don't fit
44
+ the row (large font, narrow chrome) they wrap onto a second
45
+ row. Scroll bars belong inside component content (sol-pod's
46
+ tree, etc.), not on layout chrome. */
47
+ overflow: visible;
48
+ }
49
+
50
+ .sol-menu-nav button {
51
+ background: none; border: none;
52
+ text-align: left;
53
+ padding: var(--menu-button-padding, var(--space-md, 8px) var(--space-lg, 12px));
54
+ border-radius: var(--menu-button-radius, var(--radius-sm, 4px));
55
+ color: var(--text, black) !important;
56
+ cursor: pointer; font-family: inherit;
57
+ white-space: nowrap;
58
+ overflow: hidden; text-overflow: ellipsis;
59
+ font-size: var(--font-size, var(--medium-font, 20px)) !important;
60
+ }
61
+ :host([orientation="horizontal"]) > .sol-menu-nav > button,
62
+ :host([orientation="horizontal"]) > .sol-menu-nav > .sol-menu-group {
63
+ flex-shrink: 0;
64
+ }
65
+ .sol-menu-nav button .sol-menu-icon {
66
+ display: inline-flex; align-items: center;
67
+ vertical-align: middle;
68
+ pointer-events: none;
69
+ }
70
+ .sol-menu-nav button .sol-menu-icon svg {
71
+ fill: currentColor;
72
+ }
73
+ .sol-menu-nav button .sol-menu-icon img {
74
+ height: 1.2em; width: auto;
75
+ }
76
+ .sol-menu-nav button:hover {
77
+ background: var(--menu-hover-bg, var(--hover, #f0f0f0));
78
+ color: var(--menu-hover-color, var(--accent-dark, #1976d2));
79
+ }
80
+ .sol-menu-nav button:focus-visible {
81
+ outline: 2px solid var(--accent, #4a9eff);
82
+ outline-offset: 2px;
83
+ }
84
+ .sol-menu-nav button.active {
85
+ background: var(--menu-active-bg, var(--focus-bg, #e3f2fd)) !important;
86
+ color: var(--menu-active-color, var(--accent-dark, #1976d2)) !important;
87
+ font-weight: var(--font-weight-bold, 600);
88
+ }
89
+
90
+ .sol-menu-group {
91
+ position: relative;
92
+ display: block;
93
+ }
94
+ .sol-menu-group-btn {
95
+ width: 100%;
96
+ display: flex;
97
+ align-items: center;
98
+ gap: var(--space-sm, 4px);
99
+ }
100
+ .sol-menu-group-btn::after {
101
+ content: '▸';
102
+ margin-left: auto;
103
+ font-size: var(--small-font, 16px);
104
+ opacity: 0.7;
105
+ }
106
+ :host([orientation="horizontal"]) .sol-menu-nav > .sol-menu-group > .sol-menu-group-btn::after {
107
+ content: '▾';
108
+ margin-left: var(--space-sm, 4px);
109
+ }
110
+ .sol-menu-popup {
111
+ display: none;
112
+ position: fixed;
113
+ min-width: var(--menu-popup-min-width, 160px);
114
+ padding: var(--space-md, 8px);
115
+ background: var(--surface, #fff);
116
+ border: 1px solid var(--border, #e0e0e0);
117
+ border-radius: var(--radius-md, 6px);
118
+ box-shadow: var(--shadow-popup, 0 4px 12px rgba(0,0,0,0.12));
119
+ z-index: 1000;
120
+ flex-direction: column;
121
+ gap: var(--space-xs, 2px);
122
+ }
123
+ .sol-menu-group.open > .sol-menu-popup {
124
+ display: flex;
125
+ }
126
+
127
+ /* The content area is a light-DOM child of <sol-menu>, projected through
128
+ the shadow slot, so menu-click results land in light DOM and are
129
+ reachable by page CSS and document queries. Style it directly with
130
+ sol-menu > .sol-menu-content { ... } — there is no part() hook.
131
+ overflow:hidden (not auto) by default: app chrome doesn't scroll;
132
+ components placed inside scroll on their own. */
133
+ slot { display: contents; }
134
+ ::slotted(.sol-menu-content) {
135
+ flex: 1 1 0; min-height: 0; min-width: 0;
136
+ max-width: 100%;
137
+ display: flex; flex-direction: column;
138
+ overflow: hidden;
139
+ padding: var(--menu-content-padding, var(--space-xl, 16px) var(--space-xl, 16px));
140
+ box-sizing: border-box;
141
+ }
142
+ `;
143
+
144
+ export const sheet = sheetFrom(CSS);
145
+ export default sheet;
@@ -0,0 +1,134 @@
1
+ import { sheetFrom } from '../../core/adopt.js';
2
+ import { BTN_CSS } from './buttons-css.js';
3
+
4
+ export const CSS = BTN_CSS + `
5
+ :host { display: contents; }
6
+
7
+ .modal-overlay {
8
+ position: fixed; inset: 0;
9
+ background: rgba(15,17,21,0.62);
10
+ -webkit-backdrop-filter: blur(6px);
11
+ backdrop-filter: blur(6px);
12
+ display: flex; align-items: center; justify-content: center;
13
+ z-index: 1000;
14
+ font-family: var(--font-body, system-ui, -apple-system, sans-serif);
15
+ color: var(--text, #212121);
16
+ }
17
+
18
+ .modal {
19
+ background: var(--surface, #fff);
20
+ border: 1px solid var(--border, #9aa3af);
21
+ border-radius: 12px;
22
+ box-shadow:
23
+ 0 1px 0 rgba(255,255,255,0.6) inset,
24
+ 0 4px 10px rgba(15,17,21,0.18),
25
+ 0 28px 60px -20px var(--shadow-heavy, rgba(15,17,21,0.45));
26
+ width: calc(100vw - 4vmin);
27
+ height: calc(100vh - 4vmin);
28
+ display: flex; flex-direction: column;
29
+ overflow: hidden;
30
+ }
31
+ :host([size="small"]) .modal { max-width: 460px; height: auto; min-height: 0; }
32
+ :host([size="large"]) .modal { max-width: 820px; height: auto; min-height: 0; }
33
+
34
+ .modal-header {
35
+ display: flex; align-items: center;
36
+ padding: 14px 20px;
37
+ border-bottom: 1px solid var(--border-soft, var(--border, #d6dae2));
38
+ gap: 12px; flex-shrink: 0;
39
+ background: var(--surface, #fff);
40
+ }
41
+
42
+ .modal-title {
43
+ flex: 1; font-weight: 600; font-size: 1em;
44
+ letter-spacing: -0.005em;
45
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
46
+ }
47
+
48
+ .modal-header-actions {
49
+ display: flex; align-items: center; gap: 6px; margin-right: 4px;
50
+ }
51
+
52
+ .modal-close {
53
+ background: none; border: none;
54
+ font-size: 1.15em; line-height: 1;
55
+ color: var(--text-muted, #4a525e); cursor: pointer;
56
+ padding: 6px 10px; border-radius: 6px;
57
+ transition: background 0.12s, color 0.12s;
58
+ }
59
+ .modal-close:hover { background: var(--hover, #eef0f4); color: var(--text, #0f1115); }
60
+ .modal-close:focus-visible {
61
+ outline: 3px solid var(--focus-ring, var(--accent, #1565c0));
62
+ outline-offset: 2px;
63
+ }
64
+ /* modal-close uses raw styles (not .sol-btn) to stay minimal. */
65
+
66
+ .modal-body {
67
+ flex: 1; overflow-y: auto; padding: 18px 22px;
68
+ display: flex; flex-direction: column; gap: 12px;
69
+ min-height: 0;
70
+ background: var(--surface, #fff);
71
+ }
72
+
73
+ .modal-footer {
74
+ display: flex; gap: 10px; align-items: center;
75
+ padding: 12px 20px;
76
+ border-top: 1px solid var(--border-soft, var(--border, #d6dae2));
77
+ flex-shrink: 0;
78
+ background: var(--surface-2, #f5f6f9);
79
+ }
80
+ .modal-footer:empty { display: none; }
81
+
82
+ .modal-zoom-pct { font-size: 0.8em; color: var(--text-muted, #4a525e); min-width: 3em; text-align: center; }
83
+
84
+ .modal-input {
85
+ /* Fit-width with a max-width cap; does NOT fill the row. */
86
+ width: min(100%, 50ch);
87
+ min-width: 18ch;
88
+ max-width: 50ch;
89
+ box-sizing: border-box;
90
+ /* Reset UA form-control styling so font + line-height are ours, not
91
+ the browser's per-input-type defaults (which otherwise render in
92
+ e.g. Arial/Helvetica regardless of inherited body font). */
93
+ appearance: none;
94
+ -webkit-appearance: none;
95
+ font: inherit;
96
+ line-height: 1.2;
97
+ padding: 0.4em 0.7em;
98
+ border: 1px solid var(--border-soft, var(--border, #d6dae2));
99
+ border-radius: 6px;
100
+ /* Explicit height (not min-height) so input and the adjacent
101
+ .modal-row > .sol-btn are pixel-for-pixel identical. Both compute
102
+ to: 1.2em line + 0.8em vertical padding + 2px border. */
103
+ height: calc(1.2em + 0.8em + 2px);
104
+ background: var(--surface, #fff); color: var(--text, #0f1115);
105
+ transition: border-color 0.12s, box-shadow 0.12s;
106
+ }
107
+ .modal-input:focus {
108
+ outline: none;
109
+ border-color: var(--accent, #0f4ea0);
110
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #0f4ea0) 22%, transparent);
111
+ }
112
+
113
+ .modal-label { font-size: 0.9em; color: var(--text-muted, #4a525e); }
114
+ .modal-message { padding: 8px 0; color: var(--text-muted, #4a525e); font-size: 0.95em; }
115
+ .modal-message.error { color: var(--error, #b3261e); }
116
+ .modal-note { font-size: 0.8em; color: var(--text-faint, #7a8390); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
117
+
118
+ .modal-info-banner {
119
+ background: var(--warning-bg, #fff4d4);
120
+ border: 1px solid var(--warning-border, #e2b870);
121
+ border-left: 3px solid var(--warning-border, #e2b870);
122
+ border-radius: 6px; padding: 9px 13px;
123
+ font-size: 0.88em; color: var(--warning-text, #5d4037);
124
+ flex-shrink: 0;
125
+ }
126
+
127
+ .modal-body-component {
128
+ display: flex; flex-direction: column;
129
+ width: 100%; height: 100%;
130
+ }
131
+ `;
132
+
133
+ export const sheet = sheetFrom(CSS);
134
+ export default sheet;