@gemboss/ui 0.21.0 → 0.30.2
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/CHANGELOG.md +328 -0
- package/README.md +433 -24
- package/catalog/editor.html +426 -10
- package/catalog/index.html +907 -33
- package/gemboss-ui.css +3 -3
- package/package.json +23 -3
- package/parts/components.css +5 -0
- package/parts/core.css +5 -0
- package/parts/shell.css +5 -0
- package/src/action-card.css +1 -0
- package/src/action-card.tsx +149 -0
- package/src/app-shell.css +1 -1
- package/src/assistant/chat-markdown.ts +279 -0
- package/src/assistant/chat-turns.ts +120 -0
- package/src/assistant/chat.tsx +871 -0
- package/src/assistant/engine-mark-art.ts +45 -0
- package/src/assistant/engine-mark.tsx +39 -0
- package/src/assistant/engine.tsx +697 -0
- package/src/assistant/host.tsx +3 -1
- package/src/assistant/index.ts +6 -0
- package/src/assistant-chat.css +1 -0
- package/src/assistant-engine.css +1 -0
- package/src/auth.css +1 -1
- package/src/auth.tsx +18 -2
- package/src/chat-composer.css +1 -1
- package/src/chat-plain.js +6 -0
- package/src/chat.css +1 -1
- package/src/collections.tsx +1 -0
- package/src/dialog.tsx +3 -135
- package/src/editor/controls.tsx +1 -0
- package/src/editor/frame.tsx +12 -4
- package/src/editor/index.ts +10 -1
- package/src/editor/layers.tsx +136 -0
- package/src/editor/panel.tsx +1 -0
- package/src/editor/panes.tsx +4 -3
- package/src/editor/sortable.tsx +79 -0
- package/src/editor/tree.tsx +61 -0
- package/src/editor-layers-plain.js +1 -0
- package/src/editor.css +1 -1
- package/src/engine-plain.js +1 -0
- package/src/index-table.tsx +1 -0
- package/src/index.ts +8 -3
- package/src/kit-plain.css +1 -1
- package/src/kit-plain.js +1 -1
- package/src/launcher.tsx +1 -0
- package/src/menu-layer.ts +9 -2
- package/src/minichart.css +1 -0
- package/src/minichart.tsx +165 -0
- package/src/portal.tsx +1 -0
- package/src/reactions.tsx +1 -0
- package/src/resource-list-select.tsx +1 -0
- package/src/search-dialog.tsx +146 -0
- package/src/selection.tsx +1 -0
- package/src/setup-guide.css +1 -0
- package/src/setup-guide.tsx +116 -0
- package/src/theme-script.ts +10 -0
- package/src/theme.tsx +5 -5
package/src/assistant/host.tsx
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* assistant is unmounted by the next menu click, and unmounting aborts the run. Geometry only changes
|
|
13
13
|
* class names; the subtree is never re-parented (that would remount the chat and abort the run too).
|
|
14
14
|
*/
|
|
15
|
+
import "../assistant.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
|
|
15
16
|
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState, type ReactNode } from "react";
|
|
16
17
|
|
|
17
18
|
import { DOCK_MIN_HEIGHT, SIDE_MIN_WIDTH, clampDockHeight, clampSideWidth } from "./dock";
|
|
@@ -304,7 +305,8 @@ export function AssistantHost({
|
|
|
304
305
|
aria-label={mode === "hidden" ? undefined : title}
|
|
305
306
|
>
|
|
306
307
|
{mode === "full" ? (
|
|
307
|
-
|
|
308
|
+
// data-gb-dock-chrome: what AssistantChat measures to keep its first line clear of these buttons (0.29.0).
|
|
309
|
+
<div className="gb-dock-fullchrome" data-gb-dock-chrome="">
|
|
308
310
|
{fullActions}
|
|
309
311
|
<button type="button" className="gb-dock-shrink" onClick={onShrink}>
|
|
310
312
|
{/* Two arrows pulled INTO the centre. The first attempt drew two corner brackets, which at 16px
|
package/src/assistant/index.ts
CHANGED
|
@@ -4,3 +4,9 @@ export { AssistantHost, type AssistantHostLabels, type AssistantSecondTab } from
|
|
|
4
4
|
export { AssistantProvider, SIDE_WIDTH_VAR, useAssistant, useAssistantPageFacts, type AssistantDockApi, type AssistantOptions } from "./provider";
|
|
5
5
|
export * from "./dock";
|
|
6
6
|
export { AssistantWorkspaceLayout, OpenChatTabs, SessionRail, SESSION_RAIL_EN, groupSessions, normalizeForSearch, relativeTime, type AssistantSession, type SessionGroup, type SessionRailIcons, type SessionRailLabels } from "./sessions";
|
|
7
|
+
export { BRIDGE_TONE, BridgeNotice, ENGINE_PICKER_EN, EnginePanel, EnginePicker, engineChipName, useEnginePicker, type BridgeSetup, type BridgeState, type BridgeStatus, type Choice, type EngineChoice, type EnginePickerLabels, type EnginePickerProps, type EnginePickerTab } from "./engine";
|
|
8
|
+
// 0.29.0: the chat BODY as components (the surface hands in messages and actions), its markdown, and each engine's mark.
|
|
9
|
+
export { AssistantChat, ChatAttach, ChatBubble, ChatComposer, ChatError, ChatLabelsProvider, ChatMarkdown, ChatMessage, ChatMeta, ChatNote, ChatPending, ChatStarters, ChatSteps, ChatThread, CHAT_EN, PaperclipIcon, useComposerDensity, useFullChromeRoom, type AssistantChatProps, type ChatComposerProps, type ChatFix, type ChatLabels, type ChatMarkdownProps, type ChatMessageData, type ChatStarter, type ChatStep, type ComposerDensity } from "./chat";
|
|
10
|
+
export { bareUrl, CODE_FOLD_LINES, FLEET_IMAGE_HOSTS, imageSource, linkTarget, parseBlocks, parseInline, type Block, type ImageHost, type Inline, type InlineOptions } from "./chat-markdown";
|
|
11
|
+
export { ENGINE_MARK_ART, ENGINE_MARK_FILL_RULE, EngineMark, isEngineMarkId, type EngineMarkArt, type EngineMarkId } from "./engine-mark";
|
|
12
|
+
export { atBridge, BRIDGE_GONE, bridgeTurnError, PAIRING_REJECTED, useChatTurns, type ChatTurns, type TurnError } from "./chat-turns";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.gb-chat{display:flex;flex-direction:column;min-width:0;min-height:0;height:100%;background:var(--gemboss-surface, #fff)}.gemboss-assistant-layout:not(.is-dock) .gb-chat{background:transparent}.gb-chat>.gemboss-ec-scroll{flex:1 1 auto}.gb-dock:not(.gb-dock-full) .gb-chat-head{display:none}.gb-chat-head{flex:none;box-sizing:border-box;justify-content:center}.gb-chat[data-chrome]>.gb-chat-head{padding-right:var(--gb-chat-chrome-w);min-height:var(--gb-chat-chrome-h)}.gb-chat[data-chrome]:not(:has(>.gb-chat-head))>.gemboss-ec-scroll{padding-top:var(--gb-chat-chrome-h)}.gemboss-ec-starter.gb-chat-starter{white-space:normal;border-radius:12px;text-align:left;overflow-wrap:anywhere}.gb-chat-starter-hint{display:block;margin-bottom:4px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption, 12px)}.gb-chat-label{margin:0;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption, 12px)}.gb-chat-target{color:var(--gemboss-text-muted)}.gb-chat-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption, 12px)}.gb-chat-copy{flex:none}.gb-chat-note{margin:0;align-self:center;text-align:center;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption, 12px)}.gb-chat-notice{margin:0}.gb-chat-error{display:grid;gap:8px;margin:0;overflow-wrap:anywhere}.gb-chat-cmd{display:block;padding:6px 8px;border-radius:8px;background:#0000000d;color:var(--gemboss-text);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:16px;overflow-wrap:anywhere;user-select:all}.gb-chat-original>summary{cursor:pointer;min-height:24px;display:flex;align-items:center}.gemboss-ec-input .gemboss-ec-attach-btn{flex:0 0 auto;width:44px;height:44px;border-radius:50%;padding:0;display:inline-flex;align-items:center;justify-content:center;border:0;background-color:transparent;color:var(--gemboss-text-muted);cursor:pointer}.gemboss-ec-input .gemboss-ec-attach-btn:hover:not(:disabled){background-color:var(--gemboss-hover, rgba(0, 0, 0, .05));color:var(--gemboss-text)}.gemboss-ec-input .gemboss-ec-attach-btn:focus-visible{outline:2px solid var(--gemboss-focus, var(--ui-focus, #5661f5));outline-offset:2px}.gemboss-ec-input .gemboss-ec-attach-btn:disabled{opacity:.5;cursor:default}.gemboss-ec-input .gemboss-ec-attach-btn svg{width:24px;height:24px}@media (pointer: fine){.gemboss-ec-input .gb-engine-chip{position:relative}.gemboss-ec-input .gb-engine-chip:after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:44px;z-index:1}}@media (pointer: coarse),(max-width: 47.9975em){.gb-chat-original>summary{min-height:44px}}@media (max-width: 560px){.gb-dock-fullchrome .gb-dock-shrink:not(:has(svg)){padding:0 12px;width:auto}.gb-dock-fullchrome .gb-dock-shrink:not(:has(svg)) span{position:static;width:auto;height:auto;overflow:visible;clip:auto}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.gb-engine{display:inline-flex;min-width:0;max-width:100%}.gb-engine-chip{display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:100%;box-sizing:border-box;height:var(--ui-btn-h, 28px);padding:0 24px 0 8px;font:inherit;font-size:var(--ui-fs-caption, 12px);font-weight:500;line-height:20px;white-space:nowrap;color:var(--ui-text-muted);background-color:transparent;border:1px solid transparent;border-radius:var(--ui-radius-md, 8px);cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23686b71' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center}@media (hover: hover){.gb-engine-chip:hover{color:var(--ui-text);background-color:var(--gemboss-hover, rgba(0,0,0,.05))}}@media (hover: none){.gb-engine-chip{color:var(--ui-text)}}.gb-engine-chip[aria-expanded=true]{color:var(--ui-text);background-color:var(--gemboss-hover, rgba(0,0,0,.05))}.gb-engine-chip:focus-visible{color:var(--ui-text);outline:2px solid var(--ui-focus);outline-offset:2px}.gb-engine-chiplabel{min-width:0;overflow:hidden;text-overflow:ellipsis}.gb-engine-chipsub{font-weight:450}.gb-engine-chip:disabled{cursor:default;opacity:.55}.gemboss-engine-mark{display:block;width:14px;height:14px;flex:0 0 auto}.gb-engine-chipmark{display:none}.gb-engine-chipmark .gemboss-engine-mark{width:16px;height:16px}.gemboss-ec-input:not([data-density=full]) .gb-engine-chipsub{display:none}.gemboss-ec-input:is([data-density=icon],[data-density=tight]) .gb-engine-chip.has-mark .gb-engine-chiplabel{display:none}.gemboss-ec-input:is([data-density=icon],[data-density=tight]) .gb-engine-chip.has-mark .gb-engine-chipmark{display:block}.gemboss-ec-input:is([data-density=icon],[data-density=tight]) .gb-engine:has(.has-mark){flex-shrink:0}.gb-engine-dot{flex:none;display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--ui-text-muted);vertical-align:middle}.gb-engine-dot--ok{background:var(--gemboss-success, #007f5f)}.gb-engine-dot--warn{background:#e8a10a;box-shadow:0 0 0 1px var(--gemboss-warning, #9a6700) inset}.gb-engine-dot--down{background:var(--gemboss-danger, #d72c0d)}.gb-engine-dot--idle{background:transparent;box-shadow:0 0 0 1.5px var(--ui-text-muted) inset}.gb-engine-panel{position:fixed;z-index:1000;inset:auto;margin:0;width:min(360px,calc(100vw - 16px));box-sizing:border-box;overflow:auto;overscroll-behavior:contain;padding:0 0 var(--ui-space-3, 12px);color:var(--ui-text);font-size:var(--ui-fs-caption, 12px);line-height:16px}.gb-engine-panel[hidden],.gb-engine-panel[popover]:not(:popover-open):not([data-open]){display:none}:where(.gb-engine-panel[popover]){border:0;background:none;color:inherit}.gb-engine-panel--inline{position:static;z-index:auto;overflow:visible}.gb-engine-tabs{padding:0 var(--ui-space-2, 8px)}.gb-engine-tabs>button{gap:6px}.gb-engine-pane{display:grid;gap:var(--ui-space-3, 12px);padding:var(--ui-space-3, 12px) var(--ui-space-3, 12px) 0}.gb-engine-pane p{margin:0}.gb-engine-field{display:grid;gap:6px}.gb-engine-label{font-weight:550;color:var(--ui-text-strong, var(--ui-text))}.gb-engine-note{color:var(--ui-text-muted)}.gb-engine-list{display:grid;border:1px solid var(--ui-border);border-radius:var(--ui-radius-md, 8px);overflow:hidden}.gb-engine-row{display:grid;gap:2px;min-height:44px;padding:6px 10px 6px 32px;box-sizing:border-box;position:relative;font:inherit;text-align:left;color:inherit;background:transparent;border:0;cursor:pointer}.gb-engine-row+.gb-engine-row{border-top:1px solid var(--ui-border)}.gb-engine-row:before{content:"";position:absolute;left:10px;top:50%;width:14px;height:14px;margin-top:-7px;box-sizing:border-box;border:1.5px solid var(--ui-text-muted);border-radius:50%}.gb-engine-row[aria-checked=true]{background:var(--gemboss-active-bg, #f0f1f4)}.gb-engine-row[aria-checked=true]:before{border:4.5px solid var(--ui-accent)}.gb-engine-row[aria-checked=true] .gb-engine-rowname{font-weight:600}@media (hover: hover){.gb-engine-row:hover:not(:disabled){background:var(--ui-surface-2)}}.gb-engine-row:focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.gb-engine-row:disabled{cursor:not-allowed}.gb-engine-row:disabled .gb-engine-rowname{color:var(--ui-text-muted)}.gb-engine-rowhead{display:flex;align-items:center;gap:var(--ui-space-2, 8px);min-width:0}.gb-engine-rowname{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:450}.gb-engine-opts{display:flex;flex-wrap:wrap;gap:var(--ui-space-2, 8px)}.gb-engine-opt{height:var(--ui-btn-h, 28px);padding:0 10px;box-sizing:border-box;font:inherit;font-weight:500;color:var(--ui-text);background:transparent;border:1px solid var(--ui-border);border-radius:var(--ui-radius-md, 8px);cursor:pointer}@media (hover: hover){.gb-engine-opt:hover:not(:disabled){background:var(--ui-surface-2)}}.gb-engine-opt[aria-pressed=true]{background:var(--gemboss-active-bg, #f0f1f4);border-color:var(--ui-text);font-weight:600}.gb-engine-opt:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.gb-engine-opt:disabled{opacity:.5;cursor:not-allowed}.gb-engine-select{width:100%}.gb-engine-groups{display:grid;gap:var(--ui-space-3, 12px)}.gb-engine-group{display:grid;gap:6px}.gb-engine-group+.gb-engine-group{padding-top:var(--ui-space-3, 12px);border-top:1px solid var(--ui-border)}.gb-engine-group[data-current] .gb-engine-rowname{font-weight:600}.gb-engine-problem{color:var(--gemboss-danger-strong, #b42318)}.gb-engine-notes{display:grid;gap:4px;color:var(--ui-text-muted)}.gb-engine-notes p{margin:0}.gb-engine-callout{padding:8px 10px;border-radius:var(--ui-radius-md, 8px);border:1px solid}.gb-engine-callout--warn{background:var(--gemboss-warning-soft, #fff8e0);border-color:var(--gemboss-warning-border, #f5d569);color:var(--gemboss-warning, #9a6700)}.gb-engine-callout--down{background:var(--gemboss-danger-soft, #fff0e9);border-color:var(--gemboss-danger-border, #f5c9bc);color:var(--gemboss-danger-strong, #b42318)}.gb-engine-steps ol,.gb-engine-steps ul{margin:0;padding-left:18px;display:grid;gap:4px}.gb-engine-cmd{margin:0;padding:8px 10px;border-radius:var(--ui-radius-md, 8px);background:var(--ui-surface-2);border:1px solid var(--ui-border);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;line-height:16px;white-space:pre-wrap;word-break:break-all;user-select:all;max-height:96px;overflow:auto}.gb-engine-cmd code{padding:0;border:0;background:none;font:inherit;color:inherit}.gb-engine-actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2, 8px)}.gb-engine-said{color:var(--ui-text-muted)}.gb-engine-said:empty{display:none}.gb-engine-code code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:600;letter-spacing:.04em;user-select:all}.gb-engine-rows{display:grid;grid-template-columns:auto 1fr;gap:6px 12px;margin:0}.gb-engine-rows dt{color:var(--ui-text-muted)}.gb-engine-rows dd{margin:0;display:flex;align-items:center;gap:6px;min-width:0;overflow-wrap:anywhere}.gb-engine-notice{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:4px 6px;margin:0;padding:4px 0;font-size:var(--ui-fs-caption, 12px);line-height:16px;color:var(--ui-text-muted)}.gb-engine-notice>.gb-engine-dot{margin-top:4px}.gb-engine-notice>.gb-engine-notice-link{grid-column:2;justify-self:start}.gb-engine-notice--down .gb-engine-notice-text,.gb-engine-notice--warn .gb-engine-notice-text{color:var(--ui-text)}.gb-engine-notice-text{min-width:0;overflow-wrap:anywhere}.gb-engine-notice-link{flex:none;display:inline-flex;align-items:center;min-height:24px;margin:-4px 0 -4px -4px;padding:0 4px;border:0;border-radius:4px;background:none;font:inherit;font-weight:550;color:var(--ui-accent);text-decoration:underline;text-underline-offset:2px;cursor:pointer}.gb-engine-notice-link:focus-visible{outline:2px solid var(--ui-focus);outline-offset:0}@media (pointer: coarse),(max-width: 47.9975em){.gb-engine-chip{min-height:44px}.gb-engine-opt{min-height:44px;min-width:44px}.gb-engine-notice-link{min-height:44px;margin:-14px 0 -14px -8px;padding:0 8px}}@media (prefers-reduced-motion: no-preference){.gb-engine-chip,.gb-engine-opt,.gb-engine-row{transition:background-color .12s ease,color .12s ease}}
|
package/src/auth.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gb-auth{--gb-surface: #ffffff;--gb-ink: var(--gemboss-text-strong, #1b1c1e);--gb-muted: #6d7175;--gb-line: #e1e3e5;--gb-field-line: #c9cccf;--gb-field-bg: #ffffff;--gb-field-hover: #fafafa;--gb-placeholder: #868b94;--gb-accent: #5661f5;--gb-btn: linear-gradient(120deg, #1b1c1e 0%, #000000 100%);--gb-btn-ink: #ffffff;--gb-wordmark: linear-gradient(120deg, #1b1c1e 0%, #000000 100%);--gb-hover: #f7f7f5;--gb-hover-line: #b9bbc0;--gb-err-bg: #fee2e2;--gb-err-ink: #b91c1c;--gb-err-line: transparent;--gb-card-shadow: 0 24px 64px rgba(15, 23, 42, .08);--gb-mark-bg: #0b0b0c;--gb-facet: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 120'%3E%3Cg fill='none' stroke='%23ffffff' stroke-width='0.45' stroke-linejoin='round'%3E%3Cpath d='M26,14 74,14 96,50 50,110 4,50Z'/%3E%3Cpath d='M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110'/%3E%3C/g%3E%3C/svg%3E");--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(27, 28, 30, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(86, 97, 245, .06), transparent 60%), #fafafb;--gb-page-flat: #ffffff;--gb-panel-bg: radial-gradient(900px 520px at 78% 12%, rgba(86, 97, 245, .26), transparent 62%), radial-gradient(700px 480px at 12% 96%, rgba(86, 97, 245, .12), transparent 60%), #0b0b0c;--gb-panel-ink: #f4f4f2;--gb-panel-muted: rgba(244, 244, 242, .72);--gb-panel-eyebrow: #8a93ff;--gb-panel-facet-o: .05;color-scheme:light dark;position:fixed;top:var(--vvt, 0px);left:0;right:0;height:100vh;height:var(--vvh, 100dvh);container:gb-auth / size;overflow-y:auto;background:var(--gb-page);color:var(--gb-ink);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,system-ui,sans-serif}.gb-auth-split{display:grid;grid-template-columns:1fr;min-height:100%}.gb-auth-stage{box-sizing:border-box;display:flex;min-height:100%;padding:clamp(12px,3cqh,24px) clamp(16px,4vw,24px)}.gb-auth-panel-in{position:relative;box-sizing:border-box;width:100%;max-width:520px;padding:48px clamp(32px,5vw,64px)}.gb-auth-eyebrow{margin:0 0 20px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:12px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;color:var(--gb-panel-eyebrow)}.gb-auth-panel-h{margin:0 0 16px;font-size:clamp(28px,3.2vw,40px);line-height:1.15;letter-spacing:-.02em;font-weight:700;color:var(--gb-panel-ink)}.gb-auth-panel-p{margin:0;font-size:15px;line-height:1.6;color:var(--gb-panel-muted)}.gb-auth-panel{display:none}@container gb-auth (min-width: 900px) and (min-height: 520px){.gb-auth-split{grid-template-columns:minmax(420px,1fr) minmax(0,1.05fr)}.gb-auth-split .gb-auth-stage{background:var(--gb-surface)}.gb-auth-split .gb-auth-card{border:none;box-shadow:none;max-width:400px}.gb-auth-panel{display:flex;align-items:center;position:relative;overflow:hidden;background:var(--gb-panel-bg);color:var(--gb-panel-ink)}.gb-auth-panel:before{content:"";position:absolute;inset:-45% -38% auto auto;width:132%;aspect-ratio:1;background-image:var(--gb-facet);background-size:contain;background-repeat:no-repeat;opacity:var(--gb-panel-facet-o);pointer-events:none}}.gb-auth-card{width:100%;max-width:380px;margin:auto;background:var(--gb-surface);border:1px solid var(--gb-line);border-radius:14px;padding:clamp(18px,3.5cqh,28px) 28px;box-shadow:var(--gb-card-shadow)}.gb-auth-header{text-align:center;margin-bottom:clamp(12px,3cqh,24px)}.gb-auth-mark{display:inline-flex;margin-bottom:clamp(6px,calc(6px + (100cqh - 480px)*.075),12px)}.gb-auth-mark svg,.gb-auth-mark img{width:clamp(32px,calc(32px + (100cqh - 480px)*.3),56px);height:clamp(32px,calc(32px + (100cqh - 480px)*.3),56px)}@container gb-auth (max-height: 479.98px){.gb-auth-mark{display:none}}.gb-auth-header h1{font-size:clamp(19px,2.75cqh,22px);font-weight:700;margin:0 0 clamp(0px,calc((100cqh - 560px)*.1),4px);background:var(--gb-wordmark);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.gb-auth-header p{margin:0;font-size:13px;color:var(--gb-muted)}@container gb-auth (max-height: 599.98px){.gb-auth-header p{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}.gb-auth-form{display:flex;flex-direction:column;gap:clamp(8px,1.5cqh,12px)}.gb-auth-form label{display:flex;flex-direction:column;gap:clamp(4px,.75cqh,6px);font-size:12px;font-weight:500;color:var(--gb-ink)}.gb-auth-input{box-sizing:border-box;height:32px;min-height:44px;min-width:0;padding:0 12px;font:inherit;font-size:13px;line-height:20px;border:1px solid;border-radius:8px}@media (max-width: 47.9975em){.gb-auth-input{font-size:16px}}@media (pointer: coarse){.gb-auth-input{height:auto}}.gb-auth-form input{width:100%;box-sizing:border-box;background-color:var(--gb-field-bg);border-color:var(--gb-field-line);color:var(--gb-ink)}.gb-auth-form input::placeholder{color:var(--gb-placeholder)}.gb-auth-form input:hover:not(:disabled){background-color:var(--gb-field-hover);border-color:var(--gb-hover-line)}.gb-auth-form input:focus-visible{outline:2px solid var(--gb-ink);outline-offset:1px;border-color:var(--gb-ink)}.gb-auth-field{display:flex;flex-direction:column;gap:clamp(4px,.75cqh,6px);font-size:12px;font-weight:500;color:var(--gb-ink)}.gb-auth-pw{position:relative;display:flex}.gb-auth-pw input{width:100%;padding-right:48px}.gb-auth-pw-toggle{min-height:44px;min-width:44px;position:absolute;right:0;top:0;bottom:0;display:inline-flex;align-items:center;justify-content:center;padding:0;margin:0;background:none;border:none;border-radius:8px;cursor:pointer;color:var(--gb-muted);transition:none}.gb-auth-pw-toggle:hover{color:var(--gb-ink)}.gb-auth-pw-toggle:focus-visible{outline:2px solid var(--gemboss-primary, #1b1c1e);outline-offset:-2px}.gb-auth-error{background:var(--gb-err-bg);border:1px solid var(--gb-err-line);color:var(--gb-err-ink);padding:8px 10px;font-size:13px;border-radius:6px}.gb-auth-form>.gb-auth-submit{margin-top:clamp(2px,.75cqh,6px);min-height:44px;font-size:14px;font-weight:600;border:none;border-radius:8px;background:var(--gb-btn);color:var(--gb-btn-ink);cursor:pointer;font-family:inherit;transition:opacity .15s ease,transform .15s ease}.gb-auth-form>.gb-auth-submit:hover:not(:disabled){transform:translateY(-1px)}.gb-auth-form>.gb-auth-submit:disabled{opacity:.6;cursor:not-allowed}.gb-auth-foot{margin:clamp(10px,2cqh,16px) 0 0;font-size:13px;color:var(--gb-muted);text-align:center;line-height:1.5}.gb-auth-foot a{display:inline-block;min-height:24px;line-height:24px;padding:0 2px;color:var(--gb-accent);font-weight:600;text-decoration:none}.gb-auth-foot a:hover,.gb-auth-foot a:focus-visible{text-decoration:underline}.gb-auth-card .gb-auth-help{margin:clamp(8px,1.75cqh,14px) 0 0;font-size:12px;color:var(--gb-muted);text-align:center;line-height:1.5}.gb-auth-card .gb-auth-help a{display:inline-block;min-height:24px;line-height:24px;color:var(--gb-accent);font-weight:600;text-decoration:none}.gb-auth-card .gb-auth-help a:hover,.gb-auth-card .gb-auth-help a:focus-visible{text-decoration:underline}@media (max-width: 480px){.gb-auth{background:var(--gb-page-flat)}.gb-auth-stage{padding:max(clamp(10px,3cqh,20px),env(safe-area-inset-top)) max(16px,env(safe-area-inset-right)) max(clamp(10px,3cqh,20px),env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left))}.gb-auth-card{border:none;border-radius:0;box-shadow:none;padding:0}}@container gb-auth (max-height: 399.98px){.gb-auth-header{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}@container gb-auth (max-height: 359.98px){.gb-auth-card .gb-auth-help,.gb-auth-foot{display:none}.gb-auth-stage{padding-top:max(8px,env(safe-area-inset-top));padding-bottom:max(8px,env(safe-area-inset-bottom))}}@container gb-auth (max-height: 359.98px) and (min-width: 481px){.gb-auth-card{padding-top:14px;padding-bottom:14px}}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .gb-auth{--gb-surface: #141517;--gb-ink: #f4f4f3;--gb-muted: #969c97;--gb-line: rgba(255, 255, 255, .11);--gb-field-line: rgba(255, 255, 255, .17);--gb-field-bg: #1b1c1f;--gb-field-hover: #212226;--gb-placeholder: #7f838c;--gb-accent: #8a93ff;--gb-btn: linear-gradient(120deg, #f4f4f3 0%, #dfe0e4 100%);--gb-btn-ink: #0b0b0c;--gb-wordmark: linear-gradient(120deg, #f4f4f3 0%, #c9cbd2 100%);--gb-hover: rgba(255, 255, 255, .06);--gb-hover-line: rgba(255, 255, 255, .28);--gb-err-bg: rgba(215, 44, 13, .16);--gb-err-ink: #ff9d88;--gb-err-line: rgba(245, 120, 95, .4);--gb-card-shadow: 0 24px 64px rgba(0, 0, 0, .55);--gb-mark-bg: #202127;--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(138, 147, 255, .1), transparent 60%), #0b0b0c;--gb-page-flat: #0b0b0c}}:root[data-theme=dark] .gb-auth{--gb-surface: #141517;--gb-ink: #f4f4f3;--gb-muted: #969c97;--gb-line: rgba(255, 255, 255, .11);--gb-field-line: rgba(255, 255, 255, .17);--gb-field-bg: #1b1c1f;--gb-field-hover: #212226;--gb-placeholder: #7f838c;--gb-accent: #8a93ff;--gb-btn: linear-gradient(120deg, #f4f4f3 0%, #dfe0e4 100%);--gb-btn-ink: #0b0b0c;--gb-wordmark: linear-gradient(120deg, #f4f4f3 0%, #c9cbd2 100%);--gb-hover: rgba(255, 255, 255, .06);--gb-hover-line: rgba(255, 255, 255, .28);--gb-err-bg: rgba(215, 44, 13, .16);--gb-err-ink: #ff9d88;--gb-err-line: rgba(245, 120, 95, .4);--gb-card-shadow: 0 24px 64px rgba(0, 0, 0, .55);--gb-mark-bg: #202127;--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(138, 147, 255, .1), transparent 60%), #0b0b0c;--gb-page-flat: #0b0b0c}
|
|
1
|
+
.gb-auth{--gb-surface: #ffffff;--gb-ink: var(--gemboss-text-strong, #1b1c1e);--gb-muted: #6d7175;--gb-line: #e1e3e5;--gb-field-line: #c9cccf;--gb-field-bg: #ffffff;--gb-field-hover: #fafafa;--gb-placeholder: #868b94;--gb-accent: #5661f5;--gb-btn: linear-gradient(120deg, #1b1c1e 0%, #000000 100%);--gb-btn-ink: #ffffff;--gb-wordmark: linear-gradient(120deg, #1b1c1e 0%, #000000 100%);--gb-hover: #f7f7f5;--gb-hover-line: #b9bbc0;--gb-err-bg: #fee2e2;--gb-err-ink: #b91c1c;--gb-err-line: transparent;--gb-card-shadow: 0 24px 64px rgba(15, 23, 42, .08);--gb-mark-bg: #0b0b0c;--gb-facet: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 120'%3E%3Cg fill='none' stroke='%23ffffff' stroke-width='0.45' stroke-linejoin='round'%3E%3Cpath d='M26,14 74,14 96,50 50,110 4,50Z'/%3E%3Cpath d='M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110'/%3E%3C/g%3E%3C/svg%3E");--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(27, 28, 30, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(86, 97, 245, .06), transparent 60%), #fafafb;--gb-page-flat: #ffffff;--gb-panel-bg: radial-gradient(900px 520px at 78% 12%, rgba(86, 97, 245, .26), transparent 62%), radial-gradient(700px 480px at 12% 96%, rgba(86, 97, 245, .12), transparent 60%), #0b0b0c;--gb-panel-ink: #f4f4f2;--gb-panel-muted: rgba(244, 244, 242, .72);--gb-panel-eyebrow: #8a93ff;--gb-panel-facet-o: .05;--gb-panel-grid-bg: linear-gradient(160deg, #1b1c22 0%, #0b0b0c 72%);--gb-panel-grid-line: rgba(138, 147, 255, .1);--gb-panel-grid-size: 34px;--gb-panel-grid-fade: radial-gradient(90% 80% at 30% 20%, #000, transparent 75%);color-scheme:light dark;position:fixed;top:var(--vvt, 0px);left:0;right:0;height:100vh;height:var(--vvh, 100dvh);container:gb-auth / size;overflow-y:auto;background:var(--gb-page);color:var(--gb-ink);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,system-ui,sans-serif}.gb-auth-split{display:grid;grid-template-columns:1fr;min-height:100%}.gb-auth-stage{box-sizing:border-box;display:flex;min-height:100%;padding:clamp(12px,3cqh,24px) clamp(16px,4vw,24px)}.gb-auth-panel-in{position:relative;box-sizing:border-box;width:100%;max-width:520px;padding:48px clamp(32px,5vw,64px)}.gb-auth-eyebrow{margin:0 0 20px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:12px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;color:var(--gb-panel-eyebrow)}.gb-auth-panel-h{margin:0 0 16px;font-size:clamp(28px,3.2vw,40px);line-height:1.15;letter-spacing:-.02em;font-weight:700;color:var(--gb-panel-ink)}.gb-auth-panel-p{margin:0;font-size:15px;line-height:1.6;color:var(--gb-panel-muted)}.gb-auth-panel{display:none}@container gb-auth (min-width: 900px) and (min-height: 520px){.gb-auth-split{grid-template-columns:minmax(420px,1fr) minmax(0,1.05fr)}.gb-auth-split .gb-auth-stage{background:var(--gb-surface)}.gb-auth-split .gb-auth-card{border:none;box-shadow:none;max-width:400px}.gb-auth-panel{display:flex;align-items:center;position:relative;overflow:hidden;background:var(--gb-panel-bg);color:var(--gb-panel-ink)}.gb-auth-panel:before{content:"";position:absolute;inset:-45% -38% auto auto;width:132%;aspect-ratio:1;background-image:var(--gb-facet);background-size:contain;background-repeat:no-repeat;opacity:var(--gb-panel-facet-o);pointer-events:none}.gb-auth-split .gb-auth-panel--grid{background:var(--gb-panel-grid-bg)}.gb-auth-panel.gb-auth-panel--grid:before{inset:0;width:auto;aspect-ratio:auto;background-image:linear-gradient(var(--gb-panel-grid-line) 1px,transparent 1px),linear-gradient(90deg,var(--gb-panel-grid-line) 1px,transparent 1px);background-size:var(--gb-panel-grid-size) var(--gb-panel-grid-size);background-repeat:repeat;opacity:1;-webkit-mask-image:var(--gb-panel-grid-fade);mask-image:var(--gb-panel-grid-fade)}.gb-auth-panel.gb-auth-panel--none:before{content:none}}.gb-auth-card{width:100%;max-width:380px;margin:auto;background:var(--gb-surface);border:1px solid var(--gb-line);border-radius:14px;padding:clamp(18px,3.5cqh,28px) 28px;box-shadow:var(--gb-card-shadow)}.gb-auth-header{text-align:center;margin-bottom:clamp(12px,3cqh,24px)}.gb-auth-mark{display:inline-flex;margin-bottom:clamp(6px,calc(6px + (100cqh - 480px)*.075),12px)}.gb-auth-mark svg,.gb-auth-mark img{width:clamp(32px,calc(32px + (100cqh - 480px)*.3),56px);height:clamp(32px,calc(32px + (100cqh - 480px)*.3),56px)}@container gb-auth (max-height: 479.98px){.gb-auth-mark{display:none}}.gb-auth-header h1{font-size:clamp(19px,2.75cqh,22px);font-weight:700;margin:0 0 clamp(0px,calc((100cqh - 560px)*.1),4px);background:var(--gb-wordmark);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.gb-auth-header p{margin:0;font-size:13px;color:var(--gb-muted)}@container gb-auth (max-height: 599.98px){.gb-auth-header p{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}.gb-auth-form{display:flex;flex-direction:column;gap:clamp(8px,1.5cqh,12px)}.gb-auth-form label{display:flex;flex-direction:column;gap:clamp(4px,.75cqh,6px);font-size:12px;font-weight:500;color:var(--gb-ink)}.gb-auth-input{box-sizing:border-box;height:32px;min-height:44px;min-width:0;padding:0 12px;font:inherit;font-size:13px;line-height:20px;border:1px solid;border-radius:8px}@media (max-width: 47.9975em){.gb-auth-input{font-size:16px}}@media (pointer: coarse){.gb-auth-input{height:auto}}.gb-auth-form input{width:100%;box-sizing:border-box;background-color:var(--gb-field-bg);border-color:var(--gb-field-line);color:var(--gb-ink)}.gb-auth-form input::placeholder{color:var(--gb-placeholder)}.gb-auth-form input:hover:not(:disabled){background-color:var(--gb-field-hover);border-color:var(--gb-hover-line)}.gb-auth-form input:focus-visible{outline:2px solid var(--gb-ink);outline-offset:1px;border-color:var(--gb-ink)}.gb-auth-field{display:flex;flex-direction:column;gap:clamp(4px,.75cqh,6px);font-size:12px;font-weight:500;color:var(--gb-ink)}.gb-auth-pw{position:relative;display:flex}.gb-auth-pw input{width:100%;padding-right:48px}.gb-auth-pw-toggle{min-height:44px;min-width:44px;position:absolute;right:0;top:0;bottom:0;display:inline-flex;align-items:center;justify-content:center;padding:0;margin:0;background:none;border:none;border-radius:8px;cursor:pointer;color:var(--gb-muted);transition:none}.gb-auth-pw-toggle:hover{color:var(--gb-ink)}.gb-auth-pw-toggle:focus-visible{outline:2px solid var(--gemboss-primary, #1b1c1e);outline-offset:-2px}.gb-auth-error{background:var(--gb-err-bg);border:1px solid var(--gb-err-line);color:var(--gb-err-ink);padding:8px 10px;font-size:13px;border-radius:6px}.gb-auth-form>.gb-auth-submit{margin-top:clamp(2px,.75cqh,6px);min-height:44px;font-size:14px;font-weight:600;border:none;border-radius:8px;background:var(--gb-btn);color:var(--gb-btn-ink);cursor:pointer;font-family:inherit;transition:opacity .15s ease,transform .15s ease}.gb-auth-form>.gb-auth-submit:hover:not(:disabled){transform:translateY(-1px)}.gb-auth-form>.gb-auth-submit:disabled{opacity:.6;cursor:not-allowed}.gb-auth-foot{margin:clamp(10px,2cqh,16px) 0 0;font-size:13px;color:var(--gb-muted);text-align:center;line-height:1.5}.gb-auth-foot a{display:inline-block;min-height:24px;line-height:24px;padding:0 2px;color:var(--gb-accent);font-weight:600;text-decoration:none}.gb-auth-foot a:hover,.gb-auth-foot a:focus-visible{text-decoration:underline}.gb-auth-card .gb-auth-help{margin:clamp(8px,1.75cqh,14px) 0 0;font-size:12px;color:var(--gb-muted);text-align:center;line-height:1.5}.gb-auth-card .gb-auth-help a{display:inline-block;min-height:24px;line-height:24px;color:var(--gb-accent);font-weight:600;text-decoration:none}.gb-auth-card .gb-auth-help a:hover,.gb-auth-card .gb-auth-help a:focus-visible{text-decoration:underline}@media (max-width: 480px){.gb-auth{background:var(--gb-page-flat)}.gb-auth-stage{padding:max(clamp(10px,3cqh,20px),env(safe-area-inset-top)) max(16px,env(safe-area-inset-right)) max(clamp(10px,3cqh,20px),env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left))}.gb-auth-card{border:none;border-radius:0;box-shadow:none;padding:0}}@container gb-auth (max-height: 399.98px){.gb-auth-header{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}@container gb-auth (max-height: 359.98px){.gb-auth-card .gb-auth-help,.gb-auth-foot{display:none}.gb-auth-stage{padding-top:max(8px,env(safe-area-inset-top));padding-bottom:max(8px,env(safe-area-inset-bottom))}}@container gb-auth (max-height: 359.98px) and (min-width: 481px){.gb-auth-card{padding-top:14px;padding-bottom:14px}}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .gb-auth{--gb-surface: #141517;--gb-ink: #f4f4f3;--gb-muted: #969c97;--gb-line: rgba(255, 255, 255, .11);--gb-field-line: rgba(255, 255, 255, .17);--gb-field-bg: #1b1c1f;--gb-field-hover: #212226;--gb-placeholder: #7f838c;--gb-accent: #8a93ff;--gb-btn: linear-gradient(120deg, #f4f4f3 0%, #dfe0e4 100%);--gb-btn-ink: #0b0b0c;--gb-wordmark: linear-gradient(120deg, #f4f4f3 0%, #c9cbd2 100%);--gb-hover: rgba(255, 255, 255, .06);--gb-hover-line: rgba(255, 255, 255, .28);--gb-err-bg: rgba(215, 44, 13, .16);--gb-err-ink: #ff9d88;--gb-err-line: rgba(245, 120, 95, .4);--gb-card-shadow: 0 24px 64px rgba(0, 0, 0, .55);--gb-mark-bg: #202127;--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(138, 147, 255, .1), transparent 60%), #0b0b0c;--gb-page-flat: #0b0b0c}}:root[data-theme=dark] .gb-auth{--gb-surface: #141517;--gb-ink: #f4f4f3;--gb-muted: #969c97;--gb-line: rgba(255, 255, 255, .11);--gb-field-line: rgba(255, 255, 255, .17);--gb-field-bg: #1b1c1f;--gb-field-hover: #212226;--gb-placeholder: #7f838c;--gb-accent: #8a93ff;--gb-btn: linear-gradient(120deg, #f4f4f3 0%, #dfe0e4 100%);--gb-btn-ink: #0b0b0c;--gb-wordmark: linear-gradient(120deg, #f4f4f3 0%, #c9cbd2 100%);--gb-hover: rgba(255, 255, 255, .06);--gb-hover-line: rgba(255, 255, 255, .28);--gb-err-bg: rgba(215, 44, 13, .16);--gb-err-ink: #ff9d88;--gb-err-line: rgba(245, 120, 95, .4);--gb-card-shadow: 0 24px 64px rgba(0, 0, 0, .55);--gb-mark-bg: #202127;--gb-page: radial-gradient(1200px 600px at 20% 10%, rgba(255, 255, 255, .05), transparent 60%), radial-gradient(1000px 500px at 80% 90%, rgba(138, 147, 255, .1), transparent 60%), #0b0b0c;--gb-page-flat: #0b0b0c}
|
package/src/auth.tsx
CHANGED
|
@@ -13,17 +13,31 @@
|
|
|
13
13
|
* the dark theme. Re-theme it by redefining the `--gb-*` tokens on `.gb-auth` (see auth.css), never
|
|
14
14
|
* by restyling its classes.
|
|
15
15
|
*/
|
|
16
|
+
import "./auth.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
|
|
16
17
|
import React, { useEffect, useRef, useState } from "react";
|
|
17
18
|
|
|
18
19
|
import { GemMark } from "./GemMark";
|
|
19
20
|
|
|
20
21
|
const cx = (...parts: Array<string | false | null | undefined>) => parts.filter(Boolean).join(" ");
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* What the brand panel's ground draws (0.30.0).
|
|
25
|
+
* - `"facet"` (the default, unchanged since 28/09/2026): the mark's facet lines, oversized, at 5%, over iris washes on ink.
|
|
26
|
+
* - `"grid"`: a 34px iris grid that fades out from the panel's top-left corner, on an ink gradient. gemform's sign-in
|
|
27
|
+
* drew it under its logo; Chris liked it (08/10/2026: "cái background bên dưới logo cũng đẹp"), so any sign-in can
|
|
28
|
+
* pick it. Re-tune it with `--gb-panel-grid-*` on `.gb-auth`, never by restyling the class.
|
|
29
|
+
* - `"none"`: the panel's ground alone, no pattern.
|
|
30
|
+
* A page that writes the markup itself puts `gb-auth-panel--grid` / `gb-auth-panel--none` beside `gb-auth-panel`.
|
|
31
|
+
*/
|
|
32
|
+
export type AuthBackdrop = "facet" | "grid" | "none";
|
|
33
|
+
// Whole class names, not `gb-auth-panel--${backdrop}`: written out, grep and the admin's orphan-rule gate can see them.
|
|
34
|
+
const BACKDROP: Record<AuthBackdrop, string> = { facet: "", grid: "gb-auth-panel--grid", none: "gb-auth-panel--none" };
|
|
35
|
+
|
|
22
36
|
/**
|
|
23
37
|
* The whole screen. `children` is everything inside the card below the heading: the form, then any
|
|
24
38
|
* lines under it.
|
|
25
39
|
*/
|
|
26
|
-
export function AuthLayout({ brand, tagline, mark, panel, className, children }: {
|
|
40
|
+
export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", className, children }: {
|
|
27
41
|
/** The page heading (h1) in the card. */
|
|
28
42
|
brand: React.ReactNode;
|
|
29
43
|
/** One line under the heading; the first thing shed on a short screen. */
|
|
@@ -32,6 +46,8 @@ export function AuthLayout({ brand, tagline, mark, panel, className, children }:
|
|
|
32
46
|
mark?: React.ReactNode;
|
|
33
47
|
/** The brand panel beside the card — shown only where there is room (900 wide AND 520 tall). */
|
|
34
48
|
panel?: { eyebrow?: React.ReactNode; heading: React.ReactNode; body?: React.ReactNode };
|
|
49
|
+
/** The panel's ground pattern; see `AuthBackdrop`. Only drawn where the panel is (900 wide AND 520 tall). */
|
|
50
|
+
backdrop?: AuthBackdrop;
|
|
35
51
|
className?: string;
|
|
36
52
|
children?: React.ReactNode;
|
|
37
53
|
}) {
|
|
@@ -88,7 +104,7 @@ export function AuthLayout({ brand, tagline, mark, panel, className, children }:
|
|
|
88
104
|
{/* Left OUT of aria-hidden: the words are an invitation and a screen-reader user should hear
|
|
89
105
|
them. Nothing in it is focusable — it is decoration beside the form, not a second path. */}
|
|
90
106
|
{panel ? (
|
|
91
|
-
<aside className="gb-auth-panel">
|
|
107
|
+
<aside className={cx("gb-auth-panel", BACKDROP[backdrop])}>
|
|
92
108
|
<div className="gb-auth-panel-in">
|
|
93
109
|
{panel.eyebrow ? <p className="gb-auth-eyebrow">{panel.eyebrow}</p> : null}
|
|
94
110
|
<h2 className="gb-auth-panel-h">{panel.heading}</h2>
|
package/src/chat-composer.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gemboss-ec-toolbar{flex:1 0 100%;display:flex;align-items:center;gap:4px;min-width:0}.gemboss-ec-toolbar-lead{flex:1 1 auto;display:flex;align-items:center;gap:4px;min-width:0}.gemboss-ec-toolbar-lead:empty{display:none}.gemboss-ec-toolbar-lead:empty+*{margin-left:auto}.gemboss-ec-toolbar-tools{display:flex;align-items:center;gap:4px;flex:none;min-width:0}.gemboss-ec-toolbar-tools:empty{display:none}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty){flex-wrap:nowrap;align-items:flex-end}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty)>textarea{flex:1 1 0}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty)>.gemboss-ec-toolbar{flex:0 0 auto}
|
|
1
|
+
.gemboss-ec-toolbar{flex:1 0 100%;display:flex;align-items:center;gap:4px;min-width:0}.gemboss-ec-toolbar-lead{flex:1 1 auto;display:flex;align-items:center;gap:4px;min-width:0}.gemboss-ec-toolbar-lead:empty{display:none}.gemboss-ec-toolbar-lead:empty+*{margin-left:auto}.gemboss-ec-toolbar-tools{display:flex;align-items:center;gap:4px;flex:none;min-width:0}.gemboss-ec-toolbar-tools:empty{display:none}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty){flex-wrap:nowrap;align-items:flex-end}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty)>textarea{flex:1 1 0}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty)>.gemboss-ec-toolbar{flex:0 0 auto}@media (pointer: coarse){.gemboss-ec-input .gemboss-ec-stop{width:44px;height:44px;min-width:44px}.gemboss-ec-input .gemboss-ec-stop-send{min-height:44px}}.gemboss-ec-stop{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;min-width:44px;border:none;border-radius:50%;background:var(--gemboss-critical, #d72c0d);color:#fff;cursor:pointer}.gemboss-ec-stop svg{width:12px;height:12px;fill:currentColor}.gemboss-ec-stop:disabled{opacity:.6;cursor:default}.gemboss-ec-stop:hover{filter:brightness(1.08)}.gemboss-ec-stop:focus-visible{outline:2px solid var(--gemboss-focus, var(--ui-focus, #5661f5));outline-offset:2px}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
(function(O){"use strict";var N=O.gembossUI;if(!N){O.console&&O.console.error("@gemboss/ui chat-plain.js: load kit-plain.js first (it defines gembossUI)");return}if(N.chat)return;var b={thread:"Conversation",message:"Message",send:"Send",stop:"Stop",attach:"Attach a file",copy:"Copy",copied:"Copied",copyCommand:"Copy command",originalError:"Original error",stopped:"Stopped",steps:"What it is doing",thought:"Thought",thinking:"Thinking",working:"Working",showLess:"Show less",showAll:"Show all {n} lines",openImage:"Open image"},S="http://www.w3.org/2000/svg",A=function(e){return typeof Node<"u"&&e instanceof Node};function l(e,n,r){var t=document.createElement(e);if(n)for(var a in n){var i=n[a];i==null||i===!1||(a==="text"?t.textContent=String(i):a==="className"?t.className=i:t.setAttribute(a,i===!0?"":String(i)))}return R(t,r),t}function R(e,n){return n==null||n===!1?e:Array.isArray(n)?(n.forEach(function(r){R(e,r)}),e):(e.appendChild(A(n)?n:document.createTextNode(String(n))),e)}function M(e,n,r){var t=document.createElementNS(S,"svg");if(t.setAttribute("viewBox",e),t.setAttribute("aria-hidden","true"),t.setAttribute("focusable","false"),n.forEach(function(i){var s=document.createElementNS(S,i.tag||"path");for(var o in i)o!=="tag"&&s.setAttribute(o,i[o]);t.appendChild(s)}),r)for(var a in r)t.setAttribute(a,r[a]);return t}var ae=[{host:"gemwatcher-api-production.up.railway.app",path:"/watch/artifacts/"},{host:"gemmedia-api-production.up.railway.app",path:"/"},{host:"media.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"gemmedia.ops.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"gemmedia.gemboss.ai",path:"/v1/theme-media/assets/"},{host:"cdn.shopify.com",path:"/"}],q=/[\u0000-\u001f\u007f]/g;function C(e){var n=String(e).replace(q,"").trim();return n?n.charAt(0)==="/"?n.charAt(1)==="/"||n.charAt(1)==="\\"?null:{href:n,internal:!0}:/^(https?:\/\/|mailto:)/i.test(n)?{href:n,internal:!1}:null:null}var D="https://same-origin.invalid",ie=/^\/[^/]+(\/[^/]+)*\/$/;function H(e,n){var r=String(e).replace(q,"").trim(),t;if(r.charAt(0)==="/"){var a=(n||[]).filter(function(s){return!s.host&&ie.test(s.path)});if(!a.length||r.charAt(1)==="/"||r.indexOf("\\")>=0||/%(2f|5c|25)|;/i.test(r))return null;try{t=new URL(r,D)}catch{return null}return t.origin!==D||/\.\.|%2e/i.test(t.pathname)?null:a.some(function(s){return t.pathname.indexOf(s.path)===0})?t.href.slice(D.length):null}try{t=new URL(r)}catch{return null}if(t.protocol!=="https:"||t.username||t.password||t.port)return null;var i=t.hostname.toLowerCase();return ae.concat(n||[]).some(function(s){return s.host===i&&t.pathname.indexOf(s.path)===0})?t.href:null}var T=function(e,n){return e.split(n).length-1};function P(e,n){var r=e.length,t,a,i,s,o=T(e,"("),d=T(e,")"),f=T(e,"["),c=T(e,"]");for(n=n!==!1;n&&r>0;)t=e.charAt(r-1),/[.,:;!?_~'"]/.test(t)?r-=1:t===")"&&o<d?(r-=1,d-=1):t==="]"&&f<c?(r-=1,c-=1):n=!1;if(s=e.slice(0,r),a=C(s),!a||a.internal)return null;try{i=new URL(a.href)}catch{return null}return!/^https?:$/.test(i.protocol)||!i.hostname?null:{href:a.href,rest:e.slice(r)}}var le=/(`([^`]+)`)|(\*\*([^*]+)\*\*)|(\*([^*\n]+)\*)|(!\[([^\]]*)\]\(([^)\s]+)\))|(\[([^\]]+)\]\(([^)\s]+)\))|(<(https?:\/\/[^\s<>]+)>)|(https?:\/\/[^\s<>`"*\u2000-\u206f\u3000-\u9fff\uff00-\uffef]+)/gi;function F(e,n){n=n||{};for(var r=[],t=function(m){if(m){var v=r[r.length-1];v&&v.t==="text"?v.text+=m:r.push({t:"text",text:m})}},a=new RegExp(le.source,"gi"),i=0,s;(s=a.exec(e))!==null;){if(t(e.slice(i,s.index)),s[2]!=null)r.push({t:"code",text:s[2]});else if(s[4]!=null)r.push({t:"bold",text:s[4]});else if(s[6]!=null)r.push({t:"italic",text:s[6]});else if(s[7]!=null){var o=H(s[9],n.imageHosts),d=s[8].trim();if(o)r.push({t:"image",alt:d,src:o});else{var f=C(s[9]);f&&!f.internal?r.push({t:"link",label:d||"image",href:f.href,internal:!1}):t(d)}}else if(s[10]!=null){var c=s[12],p=n.ownLink&&n.ownLink(c)?{href:c,internal:!0}:C(c);p?r.push({t:"link",label:s[11],href:p.href,internal:p.internal}):t(s[11])}else{var h=s[15]!=null&&s.index>0&&/[a-z\d]/i.test(e.charAt(s.index-1)),g=h?null:s[14]!=null?P(s[14],!1):P(s[15]);g?(r.push({t:"link",label:g.href,href:g.href,internal:!1}),t(g.rest)):t(s[0])}i=s.index+s[0].length}return t(e.slice(i)),r}var $=function(e){return/^\s*\|.*\|\s*$/.test(e)},se=function(e){return/^\s*\|?[\s:-]*-[-\s:|]*\|?\s*$/.test(e)&&e.indexOf("-")>=0},U=function(e){return e.trim().replace(/^\||\|$/g,"").split("|").map(function(n){return n.trim()})};function K(e){for(var n=String(e??"").split(`
|
|
2
|
+
`),r=[],t=0,a=[],i=function(){a.length&&r.push({t:"para",lines:a.slice()}),a.length=0};t<n.length;){var s=n[t],o;if(o=/^\s*```([\w#+.-]*)\s*$/.exec(s)){i();var d=[];for(t+=1;t<n.length&&!/^\s*```\s*$/.test(n[t]);)d.push(n[t]),t+=1;t+=1,r.push({t:"code",lang:o[1]||"",body:d.join(`
|
|
3
|
+
`)});continue}if(o=/^(#{1,6})\s+(.*)$/.exec(s)){i(),o[2].trim()&&r.push({t:"heading",level:Math.min(o[1].length,3),text:o[2].trim()}),t+=1;continue}if(/^\s*(---|\*\*\*|___)\s*$/.test(s)){i(),r.push({t:"rule"}),t+=1;continue}if($(s)&&t+1<n.length&&se(n[t+1])){i();var f=U(s),c=[];for(t+=2;t<n.length&&$(n[t]);)c.push(U(n[t])),t+=1;r.push({t:"table",head:f,rows:c});continue}if(o=/^\s*([-*+]|\d+[.)])\s+(.*)$/.exec(s)){i();for(var p=/\d/.test(o[1]),h=p?parseInt(o[1],10):void 0,g=[];t<n.length;){var m=/^\s*([-*+]|\d+[.)])\s+(.*)$/.exec(n[t]);if(!m||/\d/.test(m[1])!==p)break;g.push(m[2]),t+=1}var v={t:"list",ordered:p,items:g};h!==void 0&&h!==1&&(v.start=h),r.push(v);continue}if(/^\s*>\s?/.test(s)){i();for(var y=[];t<n.length&&/^\s*>\s?/.test(n[t]);)y.push(n[t].replace(/^\s*>\s?/,"")),t+=1;r.push({t:"quote",lines:y});continue}if(s.trim()===""){i(),t+=1;continue}a.push(s),t+=1}return i(),r}var j=12;function L(e,n,r){return F(e,n).map(function(t){if(t.t==="text")return document.createTextNode(t.text);if(t.t==="code")return l("code",{className:"gemboss-md-code",text:t.text});if(t.t==="bold")return l("strong",{text:t.text});if(t.t==="italic")return l("em",{text:t.text});if(t.t==="link"){if(n.ownLink&&n.ownLink(t.href)&&n.renderLink)return n.renderLink(t.href,t.label)||document.createTextNode(t.label);var a=l("a",{className:"gemboss-ec-md-link",href:t.href,target:t.internal?null:"_blank",rel:t.internal?null:"noopener noreferrer",text:t.label});return t.internal&&n.onNavigate&&a.addEventListener("click",function(i){i.metaKey||i.ctrlKey||i.shiftKey||(i.preventDefault(),n.onNavigate(t.href))}),a}return l("a",{className:"gemboss-md-imglink",href:t.src,target:"_blank",rel:"noopener noreferrer","aria-label":t.alt?null:r.openImage},l("img",{className:"gemboss-md-img",src:t.src,alt:t.alt,loading:"lazy",referrerpolicy:"no-referrer"}))})}function z(e,n,r){var t=[];return e.forEach(function(a,i){t=t.concat(L(a,n,r)),i<e.length-1&&t.push(l("br"))}),t}function oe(e,n){var r=e.body.split(`
|
|
4
|
+
`),t=r.length>j,a=!1,i=l("code",{text:t?r.slice(0,j).join(`
|
|
5
|
+
`):e.body}),s=l("div",{className:"gemboss-md-codeblock"},[e.lang?l("span",{className:"gemboss-md-codelang",text:e.lang}):null,l("pre",null,i)]);if(t){var o=l("button",{type:"button",className:"gemboss-md-codemore","aria-expanded":"false",text:n.showAll.replace("{n}",String(r.length))});o.addEventListener("click",function(){a=!a,i.textContent=a?e.body:r.slice(0,j).join(`
|
|
6
|
+
`),o.textContent=a?n.showLess:n.showAll.replace("{n}",String(r.length)),o.setAttribute("aria-expanded",String(a))}),s.appendChild(o)}return s}var ue={1:"h3",2:"h4",3:"h5"};function G(e,n,r){n=n||{};var t=Object.assign({},b,r||n.labels||{}),a=document.createDocumentFragment();return K(e).forEach(function(i){var s;i.t==="heading"?s=l(ue[i.level],{className:"gemboss-md-h gemboss-md-h"+i.level},L(i.text,n,t)):i.t==="code"?s=oe(i,t):i.t==="table"?s=l("div",{className:"gemboss-md-tablewrap"},l("table",{className:"gemboss-md-table"},[l("thead",null,l("tr",null,i.head.map(function(o){return l("th",null,L(o,n,t))}))),l("tbody",null,i.rows.map(function(o){return l("tr",null,i.head.map(function(d,f){return l("td",null,L(o[f]||"",n,t))}))}))])):i.t==="list"?s=l(i.ordered?"ol":"ul",{className:"gemboss-md-list",start:i.ordered&&i.start!==void 0?i.start:null},i.items.map(function(o){return l("li",null,L(o,n,t))})):i.t==="quote"?s=l("blockquote",{className:"gemboss-md-quote"},z(i.lines,n,t)):i.t==="rule"?s=l("hr",{className:"gemboss-md-rule"}):s=l("p",{className:"gemboss-md-p"},z(i.lines,n,t)),a.appendChild(s)}),a}function ce(){for(var e=12,n=1.7,r=.5,t=9.6,a=[],i=function(g){return Math.round(g*100)/100},s=function(g,m){return i(g)+" "+i(m)},o=0;o<8;o++){var d=o*Math.PI/4,f=Math.cos(d),c=Math.sin(d),p=-c,h=f;a.push(["M"+s(e+p*n,e+h*n),"L"+s(e+f*t+p*r,e+c*t+h*r),"Q"+s(e+f*(t+.6),e+c*(t+.6))+" "+s(e+f*t-p*r,e+c*t-h*r),"L"+s(e-p*n,e-h*n),"Z"].join(""))}return a.join(" ")}var V={claude:{path:ce(),label:"Claude Code"},codex:{path:"M12 2.6 20.1 7.3V16.7L12 21.4 3.9 16.7V7.3ZM12 6.9 7.6 9.45v5.1L12 17.1l4.4-2.55v-5.1Z",label:"Codex"}};function Y(e,n){var r=Object.prototype.hasOwnProperty.call(V,e)?V[e]:null;if(!r)return null;n=n||{};var t=document.createElementNS(S,"svg");if(t.setAttribute("class",n.className||"gemboss-engine-mark"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","currentColor"),n.decorative)t.setAttribute("aria-hidden","true"),t.setAttribute("focusable","false");else{t.setAttribute("role","img"),t.setAttribute("aria-label",n.title||r.label);var a=document.createElementNS(S,"title");a.textContent=n.title||r.label,t.appendChild(a)}var i=document.createElementNS(S,"path");return i.setAttribute("d",r.path),i.setAttribute("fill-rule","nonzero"),t.appendChild(i),t}function Z(e,n){var r=Object.assign({},b,n||{});return!e||!e.length?null:l("ul",{className:"gemboss-narr","aria-label":r.steps},e.map(function(t){var a=t.state||"ok",i;if(t.kind==="thinking")return i=[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:"\u2733"}),a==="running"||!t.detail?l("span",{className:"gemboss-narr-text gemboss-narr-thinking-live"},t.label||r.thinking):l("details",{className:"gemboss-narr-thinking"},[l("summary",null,t.label||r.thought),l("div",{className:"gemboss-narr-thinking-body",text:t.detail})])],l("li",{className:"gemboss-narr-row thinking "+a},i);if(t.kind==="steer")return l("li",{className:"gemboss-narr-row steer "+a},[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:"\u276F"}),l("span",{className:"gemboss-narr-text gemboss-narr-steer"},t.label)]);if(t.kind==="trace")return l("li",{className:"gemboss-narr-row trace "+a,title:t.error||null},[l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:a==="failed"?"\u2715":"\u23FA"}),t.detail?l("details",{className:"gemboss-narr-trace"},[l("summary",null,l("code",null,t.label)),l("div",{className:"gemboss-narr-trace-body"},l("code",{text:t.detail}))]):l("code",{className:"gemboss-narr-text gemboss-narr-trace-call"},t.label)]);var s=t.engine?Y(t.engine):null;return l("li",{className:"gemboss-narr-row "+a,title:t.error||null},[s?l("span",{className:"gemboss-narr-dot gemboss-narr-dot-engine"},s):l("span",{className:"gemboss-narr-dot","aria-hidden":"true",text:a==="ok"?"\u2713":a==="failed"?"\u2715":"\xB7"}),l("span",{className:"gemboss-narr-text"},[t.label,t.target?l("span",{className:"gb-chat-target"},[" ",t.target]):null])])}))}function J(e,n){e=e||{};var r=Object.assign({},b,n||{}),t=e.verbs&&e.verbs.length?e.verbs:[r.working],a=l("span",{className:"gemboss-ec-pending-verb","aria-hidden":"true",text:t[0]+"\u2026"}),i=l("span",{className:"gemboss-ec-pending-meta","aria-hidden":"true",text:"0s"}),s=l("div",{className:"gemboss-ec-pending",role:"status"},[l("span",{className:"gemboss-assistant-sronly",text:e.label||t[0]}),l("span",{className:"gemboss-ec-pending-star","aria-hidden":"true",text:"\u2733"}),e.compact?null:a,i]),o=e.since||Date.now(),d=!1,f=-1,c=function(){var h=Math.max(0,Math.floor((Date.now()-o)/1e3));i.textContent=(e.tokens>0?e.tokens+" token"+(e.tokens===1?"":"s")+" \xB7 ":"")+h+"s";var g=t.length>1?Math.floor(h/2)%t.length:0;if(g!==f&&!e.compact){f=g;var m=l("span",{className:"gemboss-ec-pending-verb","aria-hidden":"true",text:t[f]+"\u2026"});a.replaceWith(m),a=m}};c();var p=setInterval(function(){if(s.isConnected)d=!0;else if(d||Date.now()-o>6e5){clearInterval(p);return}c()},250);return s}function I(e,n,r){r=r||{};var t=document.createDocumentFragment();return!e||!e.length||(r.title&&t.appendChild(l("p",{className:"gb-chat-label"},r.title)),t.appendChild(l("div",{className:"gemboss-ec-starters"},e.map(function(a){var i=l("button",{type:"button",className:"gemboss-ec-starter gb-chat-starter"},[a.hint?l("span",{className:"gb-chat-starter-hint",text:a.hint}):null,a.label]);return i.addEventListener("click",function(){n(a)}),i})))),t}function de(e){var n=function(){try{var r=l("textarea",{readonly:!0});r.value=e,r.style.position="fixed",r.style.opacity="0",document.body.appendChild(r),r.select();var t=document.execCommand("copy");return r.remove(),t}catch{return!1}};try{if(navigator.clipboard&&navigator.clipboard.writeText)return navigator.clipboard.writeText(e).then(function(){return!0},n)}catch{}return Promise.resolve(n())}function Q(e,n,r){var t=l("button",{type:"button",className:"ui-btn ui-btn--ghost gb-chat-copy",text:n}),a=0;return t.addEventListener("click",function(){de(e).then(function(i){i&&(t.textContent=r,clearTimeout(a),a=setTimeout(function(){t.textContent=n},1500))})}),t}function X(e,n,r){var t=Object.assign({},b,r||{}),a=(n||[]).filter(function(i){return i!=null&&i!==!1&&i!==""});return!e&&!a.length?null:l("div",{className:"gb-chat-meta"},[e?Q(e,t.copy,t.copied):null].concat(a.map(function(i){return l("span",null,i)})))}function ee(e,n,r){var t=Object.assign({},b,r||{});return n?l("div",{className:"ui-notice ui-notice--danger gb-chat-error",role:"alert"},[l("div",null,n.text),n.command?l("code",{className:"gb-chat-cmd",text:n.command}):null,n.command?l("div",null,Q(n.command,t.copyCommand,t.copied)):null,l("details",{className:"gb-chat-original"},[l("summary",{text:t.originalError}),l("span",null,e)])]):l("p",{className:"ui-notice ui-notice--danger gb-chat-error",role:"alert"},e)}function _(e){return l("p",{className:"gb-chat-note"},e)}var fe={warn:"gb-engine-notice gb-engine-notice--warn",down:"gb-engine-notice gb-engine-notice--down"},he={warn:"gb-engine-dot gb-engine-dot--warn",down:"gb-engine-dot gb-engine-dot--down"};function te(e,n,r,t){if(N.bridgeNotice)return N.bridgeNotice({text:A(e)?void 0:e,node:A(e)?e:void 0,tone:n,action:r,onOpenSetup:t});var a=n==="warn"?"warn":"down",i=l("p",{className:fe[a],role:"status"},[l("span",{className:he[a],"aria-hidden":"true"}),l("span",{className:"gb-engine-notice-text"},e)]);if(t){var s=l("button",{type:"button",className:"gb-engine-notice-link",text:r||"Open setup"});s.addEventListener("click",t),i.appendChild(s)}return i}function B(e,n){return l("div",{className:"gemboss-ec-bubble"},[e,n?l("span",{className:"gemboss-ec-cursor","aria-hidden":"true"}):null])}function ne(e,n){n=n||{};var r=Object.assign({},b,n.labels||{});if(e.role==="note")return e.tone==="warn"||e.tone==="down"?te(e.text,e.tone,e.action&&e.action.label,e.action&&e.action.onClick):_(e.text);if(e.role==="user")return l("div",{className:"gemboss-ec-msg user",lang:e.lang||null},B(e.text));var t=!!e.text;return l("div",{className:"gemboss-ec-msg assistant",lang:e.lang||null},[e.steps&&e.steps.length?Z(e.steps,r):null,t?B(e.markdown===!1?e.text:G(e.text,n,r),e.pending):e.pending?J({verbs:n.pendingVerbs,since:n.since},r):null,n.renderExtra?n.renderExtra(e):null,e.warn?l("p",{className:"ui-notice ui-notice--warning gb-chat-notice"},e.warn):null,e.error?e.bridge?te(e.error,"down",null,n.onOpenSetup):ee(e.error,e.fix,r):null,e.stopped?_(r.stopped):null,!e.pending&&t?X(e.text,e.meta,r):null])}function ge(e){try{return JSON.stringify(e,function(n,r){return typeof r=="function"?"fn":A(r)?"node:"+(r.textContent||""):r})}catch{return String(Math.random())}}function pe(e,n){var r=e.querySelectorAll("details"),t=n.querySelectorAll("details"),a;for(a=0;a<r.length&&a<t.length;a++)r[a].open&&(t[a].open=!0);for(r=e.querySelectorAll(".gemboss-md-codemore"),t=n.querySelectorAll(".gemboss-md-codemore"),a=0;a<r.length&&a<t.length;a++)r[a].getAttribute("aria-expanded")==="true"&&t[a].click()}function me(e,n,r){r=r||{};var t=Object.assign({},b,r.labels||{}),a=e.__gbChat||(e.__gbChat={els:new Map,since:new Map}),i=[],s=new Map;if(!n.length&&(r.intro||r.starters&&r.starters.length)){var o=function(d){r.onStarter&&r.onStarter(d)};i.push(l("div",{className:"gemboss-ec-msg assistant"},[r.intro?B(r.intro):null,r.starters&&r.starters.length?I(r.starters,o,{title:r.startersTitle}):null,r.moreStarters&&r.moreStarters.length?I(r.moreStarters,o,{title:r.moreStartersTitle}):null]))}return n.forEach(function(d,f){var c=d.id!==void 0&&d.id!==null?"id:"+d.id:"at:"+f,p=ge(d),h=a.els.get(c);d.pending&&!d.text&&!a.since.has(c)&&a.since.set(c,Date.now());var g;h&&h.look===p?g=h.el:(g=ne(d,Object.assign({},r,{labels:t,since:a.since.get(c)})),h&&pe(h.el,g)),s.set(c,{el:g,look:p}),i.push(g)}),a.els=s,a.since.forEach(function(d,f){s.has(f)||a.since.delete(f)}),e.replaceChildren.apply(e,i),e}function ve(e,n){n=n||{};var r=Object.assign({},b,n.labels||{});e.classList.add("gemboss-ec-scroll"),e.setAttribute("role","log"),e.hasAttribute("aria-label")||e.setAttribute("aria-label",n.label||r.thread);var t=!0,a=0,i=0,s=0,o=!1,d=null,f=function(){e.scrollTop=e.scrollHeight,d=e.scrollTop},c=function(){!t||a||(a=requestAnimationFrame(function(){a=0,t&&f()}))},p=function(){i=Date.now(),o=!0,t=!1},h=function(){o=!1},g=function(){var u=e.scrollHeight-e.clientHeight-e.scrollTop,w=d!==null&&e.scrollTop===d;d=null,u>24&&!w?t=!1:u<=4&&(!o||Date.now()-i>400)&&(t=!0)},m=function(u){u.deltaY<0?p():u.deltaY>0&&h()},v=function(u){s=u.touches[0]?u.touches[0].clientY:0},y=function(u){var w=u.touches[0]?u.touches[0].clientY:0;w>s+2?p():w<s-2&&h()},k=function(u){u.key==="ArrowUp"||u.key==="PageUp"||u.key==="Home"?p():(u.key==="ArrowDown"||u.key==="PageDown"||u.key==="End")&&h()};e.addEventListener("scroll",g,{passive:!0}),e.addEventListener("wheel",m,{passive:!0}),e.addEventListener("touchstart",v,{passive:!0}),e.addEventListener("touchmove",y,{passive:!0}),e.addEventListener("keydown",k),e.addEventListener("load",c,!0);var x=new MutationObserver(c);x.observe(e,{childList:!0,subtree:!0,characterData:!0});var E=typeof ResizeObserver>"u"?null:new ResizeObserver(c);return E&&E.observe(e),f(),{el:e,setBusy:function(u){u?e.setAttribute("aria-busy","true"):e.removeAttribute("aria-busy")},toEnd:function(){t=!0,f()},destroy:function(){cancelAnimationFrame(a),e.removeEventListener("scroll",g),e.removeEventListener("wheel",m),e.removeEventListener("touchstart",v),e.removeEventListener("touchmove",y),e.removeEventListener("keydown",k),e.removeEventListener("load",c,!0),x.disconnect(),E&&E.disconnect()}}}function be(){return M("0 0 24 24",[{d:"M21.4 11.1l-8.5 8.5a5.5 5.5 0 01-7.8-7.8l8.5-8.5a3.7 3.7 0 015.2 5.2l-8.5 8.5a1.8 1.8 0 01-2.6-2.6l7.8-7.8",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}])}function ye(e){e=e||{};var n=e.label||b.attach,r=l("input",{type:"file",hidden:!0,accept:e.accept||null,multiple:e.multiple||null,tabindex:"-1"}),t=l("button",{type:"button",className:"gemboss-ec-attach-btn","aria-label":n,title:e.title||n,disabled:e.disabled||null},be());t.addEventListener("click",function(){r.click()}),r.addEventListener("change",function(){var i=Array.prototype.slice.call(r.files||[]);r.value="",i.length&&e.onFiles&&e.onFiles(i)});var a=document.createDocumentFragment();return a.appendChild(t),a.appendChild(r),a}var W=["full","compact","icon","tight"];function we(e){var n=e.querySelector(".gemboss-ec-toolbar-lead"),r=e.querySelector(".gemboss-ec-toolbar");if(n&&n.scrollWidth>n.clientWidth+1||r&&r.scrollWidth>r.clientWidth+1)return!0;var t,a=e.querySelectorAll(".gemboss-ec-chiplabel, .gb-engine-chiplabel");for(t=0;t<a.length;t++)if(a[t].offsetParent!==null&&a[t].scrollWidth>a[t].clientWidth+1)return!0;for(a=e.querySelectorAll(".gemboss-ec-chipctl, .gb-engine-chip"),t=0;t<a.length;t++)if(a[t].offsetParent!==null&&a[t].tagName!=="SELECT"&&a[t].scrollWidth>a[t].clientWidth+1)return!0;return!1}function Ne(e,n){e&&!A(e)&&(n=e,e=null),n=n||{};var r=Object.assign({},b,n.labels||{}),t=!1,a=l("textarea",{rows:n.rows||1,maxlength:n.maxLength||null,"aria-label":n.label||r.message,placeholder:n.placeholder||null}),i=l("div",{className:"gemboss-ec-toolbar-lead"},n.leading||null),s=n.tools?l("div",{className:"gemboss-ec-toolbar-tools"},n.tools):null,o=l("button",{type:"submit",disabled:!0,"aria-label":r.send,title:r.send},M("0 0 20 20",[{d:"M10.53 4.47a.75.75 0 0 0-1.06 0l-4.5 4.5a.75.75 0 0 0 1.06 1.06l3.22-3.22v8.69a.75.75 0 0 0 1.5 0v-8.69l3.22 3.22a.75.75 0 1 0 1.06-1.06l-4.5-4.5Z"}])),d=l("button",{type:"button",className:"gemboss-ec-stop","aria-label":r.stop,title:r.stop},M("0 0 12 12",[{tag:"rect",x:"1",y:"1",width:"10",height:"10",rx:"2"}])),f=l("div",{className:"gemboss-ec-toolbar"},[i,s,n.status||null,o]),c=l("div",{className:"gemboss-ec-input","data-density":"full"},[n.top||null,a,f]);e&&e.appendChild(c);var p=function(){return!a.disabled&&a.value.trim()!==""&&(!t||n.sendWhileBusy||!n.onStop)},h=function(){var u=t&&!!n.onStop,w=u?d:o,re=u?o:d;re.parentNode&&re.replaceWith(w),o.disabled=!p()},g=function(){p()&&(n.onSend&&n.onSend(a.value),n.thread&&n.thread.toEnd&&n.thread.toEnd(),n.keepValue||(a.value="",m(),h()))},m=function(){if(!(a.offsetParent===null||a.scrollHeight===0)){var u=parseFloat(getComputedStyle(a).maxHeight)||84;a.style.height="auto";var w=a.scrollHeight+(a.offsetHeight-a.clientHeight);a.style.height=Math.min(w,u)+"px",a.style.overflowY=w>u?"auto":"hidden"}};a.addEventListener("input",function(){m(),h(),n.onChange&&n.onChange(a.value)}),a.addEventListener("keydown",function(u){n.onKeyDown&&n.onKeyDown(u),!u.defaultPrevented&&u.key==="Enter"&&!u.shiftKey&&!u.isComposing&&u.keyCode!==229&&(u.preventDefault(),g())}),o.addEventListener("click",function(u){u.preventDefault(),g()}),d.addEventListener("click",function(){n.onStop&&n.onStop(),a.focus()});var v=!1,y=function(){if(!(v||c.offsetParent===null)){v=!0;for(var u=0;u<W.length&&(c.setAttribute("data-density",W[u]),!(u===W.length-1||!we(c)));u++);v=!1,n.onDensity&&n.onDensity(c.getAttribute("data-density"))}},k=-1,x=typeof ResizeObserver>"u"?null:new ResizeObserver(function(){c.clientWidth!==k&&(k=c.clientWidth,y(),m())});x&&x.observe(c);var E=new MutationObserver(function(){v||y()});return E.observe(i,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-label","title","aria-label"]}),document.fonts&&document.fonts.ready&&document.fonts.ready.then(y),requestAnimationFrame(function(){y(),m()}),{el:c,textarea:a,value:function(){return a.value},setValue:function(u){a.value=u==null?"":String(u),m(),h()},setBusy:function(u){t=!!u,h()},setDisabled:function(u){a.disabled=!!u,h()},focus:function(){a.focus()},measure:y,destroy:function(){x&&x.disconnect(),E.disconnect(),c.remove()}}}var xe="The bridge on your machine is not responding: it was stopped, or the machine just slept. The panel is checking again; rerun the install command if it does not come back.",Ee="The bridge on your machine rejected this browser's pairing code (it was installed with another code). Pair again in Setup.";function Se(e,n){return e&&typeof e=="object"&&(e.atBridge=!0,n!==void 0&&(e.status=n)),e}function Ae(e,n){return n=n||{},e&&e.name==="AbortError"?{error:null,bridge:!1,stopped:!0}:e&&e.atBridge&&e.status===401?{error:n.rejected||Ee,bridge:!0,stopped:!1}:e&&e.atBridge&&(e instanceof TypeError||e.name==="TimeoutError")?{error:n.gone||xe,bridge:!0,stopped:!1}:{error:e&&e.message||String(e),bridge:!1,stopped:!1}}N.engineMark||(N.engineMark=Y),N.chat={markdown:G,parseBlocks:K,parseInline:F,linkTarget:C,imageSource:H,message:ne,render:me,thread:ve,steps:Z,pending:J,starters:I,meta:X,error:ee,note:_,composer:Ne,attach:ye,labels:b,atBridge:Se,turnError:Ae}})(typeof globalThis<"u"?globalThis:this);
|
package/src/chat.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gemboss-ec-head{padding:16px;border-bottom:1px solid var(--gemboss-divider);display:flex;flex-direction:column;gap:2px}.gemboss-ec-title{font-family:var(--gemboss-serif);font-size:15px;font-weight:600}.gemboss-ec-sub{font-size:12px;color:var(--gemboss-text-muted)}.gemboss-ec-scroll{flex:1;min-height:0;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:16px;scrollbar-gutter:stable}.gemboss-ec-scroll{scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-ec-scroll::-webkit-scrollbar{width:9px}.gemboss-ec-scroll::-webkit-scrollbar-track{background:transparent}.gemboss-ec-scroll::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:6px;border:2px solid transparent;background-clip:content-box}.gemboss-ec-msg{display:flex;flex-direction:column;gap:8px;max-width:100%}.gemboss-ec-msg.user{align-items:flex-end}.gemboss-ec-msg.assistant{align-items:flex-start}.gemboss-ec-bubble{font-size:var(--gemboss-fs-body);line-height:1.5;padding:12px;border-radius:16px;max-width:min(90%,68ch);white-space:pre-wrap;word-break:break-word}.gemboss-ec-msg.user .gemboss-ec-bubble{background:var(--gemboss-primary);color:var(--gemboss-on-primary, #fff);border-bottom-right-radius:4px}.gemboss-ec-msg.assistant .gemboss-ec-bubble{background:var(--gemboss-surface);color:var(--gemboss-text);border:1px solid var(--gemboss-divider);border-bottom-left-radius:4px}.gemboss-ec-input button[type=submit] svg{width:18px;height:18px;fill:currentColor}.gemboss-ec-pending{display:inline-flex;align-items:center;gap:8px;padding:6px 2px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-ec-pending-star{color:var(--gemboss-primary);font-size:12px;line-height:1;animation:gemboss-star-pulse 1.1s ease-in-out infinite}.gemboss-ec-pending-verb{color:var(--gemboss-text);animation:gemboss-verb-in .4s ease-out}.gemboss-ec-pending-meta{font-variant-numeric:tabular-nums;opacity:.7;font-size:var(--gemboss-fs-caption)}@keyframes gemboss-star-pulse{0%,to{transform:scale(.85);opacity:.55}50%{transform:scale(1.15);opacity:1}}@keyframes gemboss-verb-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:none}}.gemboss-ec-cursor{display:inline-block;width:2px;height:1.05em;margin-left:2px;vertical-align:-2px;background:var(--gemboss-primary);border-radius:2px;animation:gemboss-cursor-blink 1s steps(1) infinite}@keyframes gemboss-cursor-blink{0%,45%{opacity:1}50%,95%{opacity:.15}to{opacity:1}}@media (prefers-reduced-motion: reduce){.gemboss-ec-pending-star,.gemboss-ec-cursor{animation:none}}.gemboss-ec-md-link{color:var(--gemboss-primary-dark);font-weight:600;text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--gemboss-primary) 35%,transparent);cursor:pointer}.gemboss-ec-md-link:hover{border-bottom-color:var(--gemboss-primary)}.gemboss-ec-starters{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.gemboss-ec-starter{text-align:left;font-size:13px;padding:6px 12px;border-radius:var(--gemboss-radius-full);cursor:pointer;background:var(--gemboss-surface);border:1px solid var(--gemboss-divider);color:var(--gemboss-text);white-space:nowrap;max-width:100%}.gemboss-ec-starter:hover{border-color:var(--gemboss-primary);background:#5661f50f}.gemboss-ec-input{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin:12px;padding:8px;border:1px solid var(--gemboss-divider);border-radius:16px;background:var(--gemboss-surface);transition:border-color var(--gemboss-transition-fast) ease,box-shadow var(--gemboss-transition-fast) ease}.gemboss-ec-input:focus-within{border-color:var(--gemboss-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--gemboss-primary) 12%,transparent)}.gemboss-ec-input textarea{flex:1 0 100%;min-width:0;width:100%;box-sizing:border-box;resize:none;border-radius:0;background:transparent;border:1px solid transparent;padding:6px 8px;font-size:var(--gemboss-fs-body);font-family:inherit;min-height:0;max-height:84px;line-height:1.5;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-ec-input textarea::-webkit-scrollbar{width:7px}.gemboss-ec-input textarea::-webkit-scrollbar-track{background:transparent}.gemboss-ec-input textarea::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:4px;border:2px solid transparent;background-clip:content-box}.gemboss-ec-input textarea:focus{outline:none}.gemboss-ec-input button[type=submit]{flex:0 0 auto;width:44px;height:44px;min-width:44px;min-height:44px;border-radius:50%;border:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;background:var(--gemboss-primary);color:var(--gemboss-on-primary, #fff);font-size:16px;font-weight:700;transition:background var(--gemboss-transition-fast) ease,filter var(--gemboss-transition-fast) ease}.gemboss-ec-input button[type=submit]:hover:not(:disabled){background:var(--gemboss-primary-dark)}.gemboss-ec-input button[type=submit]:active:not(:disabled){background:var(--gemboss-primary-dark);filter:brightness(.94)}.gemboss-ec-input button[type=submit]:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gemboss-ec-input button[type=submit]:disabled{background:var(--gemboss-divider);color:var(--gemboss-text-muted);opacity:1;cursor:default}.gemboss-narr{list-style:none;margin:0;padding:8px 0 0;display:flex;flex-direction:column;gap:8px}.gemboss-narr-row{display:flex;align-items:center;gap:8px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-narr-dot{width:16px;height:16px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:10px;flex:0 0 auto}.gemboss-narr-row.ok .gemboss-narr-dot{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gemboss-narr-row.failed .gemboss-narr-dot{background:#fde8e6;color:var(--gemboss-danger)}.gemboss-narr-row.running .gemboss-narr-dot{background:transparent}.gemboss-narr-dot-engine{background:transparent!important;color:inherit}.gemboss-narr-row.ok .gemboss-narr-dot-engine{color:var(--gemboss-text)}.gemboss-narr-row.failed .gemboss-narr-dot-engine{color:var(--gemboss-danger)}.gemboss-narr-row.ok .gemboss-narr-text,.gemboss-narr-row.failed .gemboss-narr-text{color:var(--gemboss-text)}.gemboss-narr-row.steer .gemboss-narr-dot{background:transparent;color:var(--gemboss-text-muted)}.gemboss-narr-steer{color:var(--gemboss-text);font-weight:500;overflow-wrap:anywhere}.gemboss-narr-spin{width:11px;height:11px;border:2px solid var(--gemboss-divider-soft);border-top-color:var(--gemboss-primary);border-radius:50%;animation:gemboss-spin .7s linear infinite}@keyframes gemboss-spin{to{transform:rotate(360deg)}}.gemboss-narr-row.thinking{align-items:flex-start}.gemboss-narr-row.thinking .gemboss-narr-dot{color:var(--gemboss-text-muted);background:transparent}.gemboss-narr-thinking-live{font-style:italic;color:var(--gemboss-text-muted);white-space:pre-wrap;opacity:.9;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-thinking{font-size:var(--gemboss-fs-caption)}.gemboss-narr-thinking>summary{cursor:pointer;color:var(--gemboss-text-muted);list-style:none;user-select:none}.gemboss-narr-thinking>summary::-webkit-details-marker{display:none}.gemboss-narr-thinking>summary:before{content:"\25b8 "}.gemboss-narr-thinking[open]>summary:before{content:"\25be "}.gemboss-narr-thinking-body{margin-top:6px;padding:8px;border-left:2px solid var(--gemboss-divider-soft);color:var(--gemboss-text-muted);font-style:italic;white-space:pre-wrap;line-height:1.5}.gemboss-narr-row.trace code{font-family:var(--gemboss-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);font-size:var(--gemboss-fs-caption);word-break:break-word}.gemboss-narr-trace-call{color:var(--gemboss-text-muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-trace{font-size:var(--gemboss-fs-caption);min-width:0}.gemboss-narr-trace>summary{cursor:pointer;color:var(--gemboss-text-muted);list-style:none;user-select:none;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-trace[open]>summary{display:block;overflow:visible}.gemboss-narr-trace>summary::-webkit-details-marker{display:none}.gemboss-narr-trace>summary,.gemboss-narr-thinking>summary{min-height:24px;box-sizing:border-box;padding-block:2px}.gemboss-narr-trace>summary:before{content:"\25b8 "}.gemboss-narr-trace[open]>summary:before{content:"\25be "}.gemboss-narr-trace-body{margin-top:6px;padding:8px;border-left:2px solid var(--gemboss-divider-soft);color:var(--gemboss-text-muted);white-space:pre-wrap;line-height:1.5;overflow-x:auto}@media (max-width: 640px){.gemboss-ec-input textarea{min-height:0}.gemboss-ec-scroll{padding:12px}}.gemboss-ec-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.gemboss-ec-chip{background:var(--gemboss-surface);border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-full);padding:8px 16px;font-size:13px;cursor:pointer;color:var(--gemboss-text);min-height:44px}.gemboss-ec-chip:hover{border-color:var(--gemboss-primary);color:var(--gemboss-active-fg)}.gemboss-ec-chip:disabled{opacity:.5;cursor:default}@media (pointer: fine){.gemboss-ec-starters{row-gap:16px}.gemboss-ec-tab,.gemboss-ec-starter,.gemboss-ec-upload,.gemboss-ec-enginepick button,.gemboss-ec-workmode,.gemboss-ec-input .gemboss-ec-attach-btn,.gemboss-ec-stop,.gemboss-ec-stop-send,.gemboss-ec-input button[type=submit]{position:relative}.gemboss-ec-tab:after,.gemboss-ec-starter:after,.gemboss-ec-upload:after,.gemboss-ec-enginepick button:after,.gemboss-ec-workmode:before,.gemboss-ec-input .gemboss-ec-attach-btn:after,.gemboss-ec-stop:after,.gemboss-ec-stop-send:after,.gemboss-ec-input button[type=submit]:after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:44px;pointer-events:auto;z-index:1}}@media (pointer: coarse){.gemboss-ec-input button[type=submit]{width:44px;height:44px;font-size:17px}.gemboss-ec-starter,.gemboss-ec-opt,.gemboss-ec-input textarea{min-height:44px}}.gemboss-md-p{margin:0 0 8px}.gemboss-md-p:last-child{margin-bottom:0}.gemboss-md-h{margin:16px 0 6px;font-weight:650;line-height:1.3}.gemboss-md-h:first-child{margin-top:0}.gemboss-md-h1{font-size:17px}.gemboss-md-h2{font-size:15px}.gemboss-md-h3{font-size:var(--gemboss-fs-body);color:var(--gemboss-text-subdued, #616161)}.gemboss-md-list{margin:0 0 8px;padding-left:20px}.gemboss-md-list li{margin:2px 0}.gemboss-md-quote{margin:0 0 8px;padding:2px 0 2px 12px;border-left:3px solid var(--gemboss-border, #e3e3e3);color:var(--gemboss-text-subdued, #616161)}.gemboss-md-rule{margin:12px 0;border:0;border-top:1px solid var(--gemboss-border, #e3e3e3)}.gemboss-md-code{padding:1px 6px;border-radius:6px;background:var(--gemboss-surface-subdued, #f1f1f1);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em;word-break:break-word}.gemboss-md-tablewrap{margin:0 0 12px;overflow-x:auto}.gemboss-md-table{border-collapse:collapse;font-size:var(--gemboss-fs-caption);min-width:100%}.gemboss-md-table th,.gemboss-md-table td{border:1px solid var(--gemboss-border, #e3e3e3);padding:6px 8px;text-align:left;vertical-align:top;white-space:nowrap}.gemboss-md-table th{background:var(--gemboss-surface-subdued, #f7f7f7);font-weight:600}.gemboss-md-imglink{display:inline-block;max-width:100%;margin:4px 0 8px;border-radius:8px;line-height:0}.gemboss-md-imglink:focus-visible{outline:2px solid var(--gemboss-focus, var(--ui-focus, #5661f5));outline-offset:2px}.gemboss-md-img{display:block;max-width:100%;max-height:320px;height:auto;border:1px solid var(--gemboss-border, #e3e3e3);border-radius:8px;background:var(--gemboss-surface-subdued, #f7f7f7);object-fit:contain}.gemboss-md-codeblock{position:relative;margin:0 0 12px;border:1px solid var(--gemboss-border, #e3e3e3);border-radius:8px;background:var(--gemboss-surface-subdued, #f7f7f7);overflow:hidden}.gemboss-md-codelang{display:block;padding:4px 12px 0;color:var(--gemboss-text-subdued, #8a8a8a);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}.gemboss-md-codeblock pre{margin:0;padding:8px 12px;overflow-x:auto}.gemboss-md-codeblock code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5;white-space:pre}.gemboss-md-codemore{display:block;width:100%;padding:6px 12px;border:0;border-top:1px solid var(--gemboss-border, #e3e3e3);background:transparent;color:var(--gemboss-text-subdued, #616161);font-size:12px;text-align:left;cursor:pointer}.gemboss-md-codemore:hover{background:#00000008}.gemboss-narr-row.source{align-items:flex-start}.gemboss-narr-source{min-width:0;flex:1}.gemboss-narr-source-head{font-size:11px;color:var(--gemboss-text-muted, #686b71);margin-bottom:4px}.gemboss-narr-source-head code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gemboss-narr-source-code{margin:0;padding:8px 12px;border-radius:8px;max-height:220px;overflow:auto;background:var(--gemboss-primary-soft, #f2f3f5);border:1px solid var(--gemboss-divider, #e5e7ea);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--gemboss-fs-micro);line-height:17px;white-space:pre;tab-size:2}.gemboss-narr-source-code .c-com{color:#6a7a86;font-style:italic}.gemboss-narr-source-code .c-str{color:#9a3412}.gemboss-narr-source-code .c-num{color:#1d6fa5}.gemboss-narr-source-code .c-kw{color:#7c3aed;font-weight:600}.gemboss-narr-source-code .c-key{color:#0b6b3a}.gemboss-narr-source-code .c-tag{color:#b0197a}.gemboss-narr-source-code .c-attr{color:#7c3aed}.gemboss-narr-source-code .c-pun{color:#6a6d73}@media (max-width: 520px){.gemboss-narr-source-code{max-height:160px;font-size:11px}}.gemboss-narr-dot-quiet{visibility:hidden}
|
|
1
|
+
.gemboss-ec-head{padding:16px;border-bottom:1px solid var(--gemboss-divider);display:flex;flex-direction:column;gap:2px}.gemboss-ec-title{font-family:var(--gemboss-serif);font-size:15px;font-weight:600}.gemboss-ec-sub{font-size:12px;color:var(--gemboss-text-muted)}.gemboss-ec-scroll{flex:1;min-height:0;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:16px;scrollbar-gutter:stable}.gemboss-ec-scroll{scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-ec-scroll::-webkit-scrollbar{width:9px}.gemboss-ec-scroll::-webkit-scrollbar-track{background:transparent}.gemboss-ec-scroll::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:6px;border:2px solid transparent;background-clip:content-box}.gemboss-ec-msg{display:flex;flex-direction:column;gap:8px;max-width:100%}.gemboss-ec-msg.user{align-items:flex-end}.gemboss-ec-msg.assistant{align-items:flex-start}.gemboss-ec-bubble{font-size:var(--gemboss-fs-body);line-height:1.5;padding:12px;border-radius:16px;max-width:min(90%,68ch);white-space:pre-wrap;word-break:break-word}.gemboss-ec-msg.user .gemboss-ec-bubble{background:var(--gemboss-primary);color:var(--gemboss-on-primary, #fff);border-bottom-right-radius:4px}.gemboss-ec-msg.assistant .gemboss-ec-bubble{background:var(--gemboss-surface);color:var(--gemboss-text);border:1px solid var(--gemboss-divider);border-bottom-left-radius:4px}.gemboss-ec-toolbar>button[type=submit] svg{width:18px;height:18px;fill:currentColor}.gemboss-ec-pending{display:inline-flex;align-items:center;gap:8px;padding:6px 2px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-ec-pending-star{color:var(--gemboss-primary);font-size:12px;line-height:1;animation:gemboss-star-pulse 1.1s ease-in-out infinite}.gemboss-ec-pending-verb{color:var(--gemboss-text);animation:gemboss-verb-in .4s ease-out}.gemboss-ec-pending-meta{font-variant-numeric:tabular-nums;opacity:.7;font-size:var(--gemboss-fs-caption)}@keyframes gemboss-star-pulse{0%,to{transform:scale(.85);opacity:.55}50%{transform:scale(1.15);opacity:1}}@keyframes gemboss-verb-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:none}}.gemboss-ec-cursor{display:inline-block;width:2px;height:1.05em;margin-left:2px;vertical-align:-2px;background:var(--gemboss-primary);border-radius:2px;animation:gemboss-cursor-blink 1s steps(1) infinite}@keyframes gemboss-cursor-blink{0%,45%{opacity:1}50%,95%{opacity:.15}to{opacity:1}}@media (prefers-reduced-motion: reduce){.gemboss-ec-pending-star,.gemboss-ec-cursor{animation:none}}.gemboss-ec-md-link{color:var(--gemboss-primary-dark);font-weight:600;text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--gemboss-primary) 35%,transparent);cursor:pointer}.gemboss-ec-md-link:hover{border-bottom-color:var(--gemboss-primary)}.gemboss-ec-starters{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.gemboss-ec-starter{text-align:left;font-size:13px;padding:6px 12px;border-radius:var(--gemboss-radius-full);cursor:pointer;background:var(--gemboss-surface);border:1px solid var(--gemboss-divider);color:var(--gemboss-text);white-space:nowrap;max-width:100%}.gemboss-ec-starter:hover{border-color:var(--gemboss-primary);background:#5661f50f}.gemboss-ec-input{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin:12px;padding:8px;border:1px solid var(--gemboss-divider);border-radius:16px;background:var(--gemboss-surface);transition:border-color var(--gemboss-transition-fast) ease,box-shadow var(--gemboss-transition-fast) ease}.gemboss-ec-input:focus-within{border-color:var(--gemboss-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--gemboss-primary) 12%,transparent)}.gemboss-ec-input textarea{flex:1 0 100%;min-width:0;width:100%;box-sizing:border-box;resize:none;border-radius:0;background:transparent;border:1px solid transparent;padding:6px 8px;font-size:var(--gemboss-fs-body);font-family:inherit;min-height:0;max-height:84px;line-height:1.5;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-ec-input textarea::-webkit-scrollbar{width:7px}.gemboss-ec-input textarea::-webkit-scrollbar-track{background:transparent}.gemboss-ec-input textarea::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:4px;border:2px solid transparent;background-clip:content-box}.gemboss-ec-input textarea:focus{outline:none}.gemboss-ec-toolbar>button[type=submit]{flex:0 0 auto;width:44px;height:44px;min-width:44px;min-height:44px;border-radius:50%;border:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;background:var(--gemboss-primary);color:var(--gemboss-on-primary, #fff);font-size:16px;font-weight:700;transition:background var(--gemboss-transition-fast) ease,filter var(--gemboss-transition-fast) ease}.gemboss-ec-toolbar>button[type=submit]:hover:not(:disabled){background:var(--gemboss-primary-dark)}.gemboss-ec-toolbar>button[type=submit]:active:not(:disabled){background:var(--gemboss-primary-dark);filter:brightness(.94)}.gemboss-ec-toolbar>button[type=submit]:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gemboss-ec-toolbar>button[type=submit]:disabled{background:var(--gemboss-divider);color:var(--gemboss-text-muted);opacity:1;cursor:default}.gemboss-narr{list-style:none;margin:0;padding:8px 0 0;display:flex;flex-direction:column;gap:8px}.gemboss-narr-row{display:flex;align-items:center;gap:8px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-narr-dot{width:16px;height:16px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:10px;flex:0 0 auto}.gemboss-narr-row.ok .gemboss-narr-dot{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gemboss-narr-row.failed .gemboss-narr-dot{background:#fde8e6;color:var(--gemboss-danger)}.gemboss-narr-row.running .gemboss-narr-dot{background:transparent}.gemboss-narr-dot-engine{background:transparent!important;color:inherit}.gemboss-narr-row.ok .gemboss-narr-dot-engine{color:var(--gemboss-text)}.gemboss-narr-row.failed .gemboss-narr-dot-engine{color:var(--gemboss-danger)}.gemboss-narr-row.ok .gemboss-narr-text,.gemboss-narr-row.failed .gemboss-narr-text{color:var(--gemboss-text)}.gemboss-narr-row.steer .gemboss-narr-dot{background:transparent;color:var(--gemboss-text-muted)}.gemboss-narr-steer{color:var(--gemboss-text);font-weight:500;overflow-wrap:anywhere}.gemboss-narr-spin{width:11px;height:11px;border:2px solid var(--gemboss-divider-soft);border-top-color:var(--gemboss-primary);border-radius:50%;animation:gemboss-spin .7s linear infinite}@keyframes gemboss-spin{to{transform:rotate(360deg)}}.gemboss-narr-row.thinking{align-items:flex-start}.gemboss-narr-row.thinking .gemboss-narr-dot{color:var(--gemboss-text-muted);background:transparent}.gemboss-narr-thinking-live{font-style:italic;color:var(--gemboss-text-muted);white-space:pre-wrap;opacity:.9;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-thinking{font-size:var(--gemboss-fs-caption)}.gemboss-narr-thinking>summary{cursor:pointer;color:var(--gemboss-text-muted);list-style:none;user-select:none}.gemboss-narr-thinking>summary::-webkit-details-marker{display:none}.gemboss-narr-thinking>summary:before{content:"\25b8 "}.gemboss-narr-thinking[open]>summary:before{content:"\25be "}.gemboss-narr-thinking-body{margin-top:6px;padding:8px;border-left:2px solid var(--gemboss-divider-soft);color:var(--gemboss-text-muted);font-style:italic;white-space:pre-wrap;line-height:1.5}.gemboss-narr-row.trace code{font-family:var(--gemboss-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);font-size:var(--gemboss-fs-caption);word-break:break-word}.gemboss-narr-trace-call{color:var(--gemboss-text-muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-trace{font-size:var(--gemboss-fs-caption);min-width:0}.gemboss-narr-trace>summary{cursor:pointer;color:var(--gemboss-text-muted);list-style:none;user-select:none;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-trace[open]>summary{display:block;overflow:visible}.gemboss-narr-trace>summary::-webkit-details-marker{display:none}.gemboss-narr-trace>summary,.gemboss-narr-thinking>summary{min-height:24px;box-sizing:border-box;padding-block:2px}.gemboss-narr-trace>summary:before{content:"\25b8 "}.gemboss-narr-trace[open]>summary:before{content:"\25be "}.gemboss-narr-trace-body{margin-top:6px;padding:8px;border-left:2px solid var(--gemboss-divider-soft);color:var(--gemboss-text-muted);white-space:pre-wrap;line-height:1.5;overflow-x:auto}@media (max-width: 640px){.gemboss-ec-input textarea{min-height:0}.gemboss-ec-scroll{padding:12px}}.gemboss-ec-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.gemboss-ec-chip{background:var(--gemboss-surface);border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-full);padding:8px 16px;font-size:13px;cursor:pointer;color:var(--gemboss-text);min-height:44px}.gemboss-ec-chip:hover{border-color:var(--gemboss-primary);color:var(--gemboss-active-fg)}.gemboss-ec-chip:disabled{opacity:.5;cursor:default}@media (pointer: fine){.gemboss-ec-starters{row-gap:16px}.gemboss-ec-tab,.gemboss-ec-starter,.gemboss-ec-upload,.gemboss-ec-workmode,.gemboss-ec-input .gemboss-ec-attach-btn,.gemboss-ec-stop,.gemboss-ec-stop-send,.gemboss-ec-toolbar>button[type=submit]{position:relative}.gemboss-ec-tab:after,.gemboss-ec-starter:after,.gemboss-ec-upload:after,.gemboss-ec-workmode:before,.gemboss-ec-input .gemboss-ec-attach-btn:after,.gemboss-ec-stop:after,.gemboss-ec-stop-send:after,.gemboss-ec-toolbar>button[type=submit]:after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:44px;pointer-events:auto;z-index:1}}@media (pointer: coarse){.gemboss-ec-toolbar>button[type=submit]{width:44px;height:44px;font-size:17px}.gemboss-ec-starter,.gemboss-ec-opt,.gemboss-ec-input textarea{min-height:44px}}.gemboss-md-p{margin:0 0 8px}.gemboss-md-p:last-child{margin-bottom:0}.gemboss-md-h{margin:16px 0 6px;font-weight:650;line-height:1.3}.gemboss-md-h:first-child{margin-top:0}.gemboss-md-h1{font-size:17px}.gemboss-md-h2{font-size:15px}.gemboss-md-h3{font-size:var(--gemboss-fs-body);color:var(--gemboss-text-subdued, #616161)}.gemboss-md-list{margin:0 0 8px;padding-left:20px}.gemboss-md-list li{margin:2px 0}.gemboss-md-quote{margin:0 0 8px;padding:2px 0 2px 12px;border-left:3px solid var(--gemboss-border, #e3e3e3);color:var(--gemboss-text-subdued, #616161)}.gemboss-md-rule{margin:12px 0;border:0;border-top:1px solid var(--gemboss-border, #e3e3e3)}.gemboss-md-code{padding:1px 6px;border-radius:6px;background:var(--gemboss-surface-subdued, #f1f1f1);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em;word-break:break-word}.gemboss-md-tablewrap{margin:0 0 12px;overflow-x:auto}.gemboss-md-table{border-collapse:collapse;font-size:var(--gemboss-fs-caption);min-width:100%}.gemboss-md-table th,.gemboss-md-table td{border:1px solid var(--gemboss-border, #e3e3e3);padding:6px 8px;text-align:left;vertical-align:top;white-space:nowrap}.gemboss-md-table th{background:var(--gemboss-surface-subdued, #f7f7f7);font-weight:600}.gemboss-md-imglink{display:inline-block;max-width:100%;margin:4px 0 8px;border-radius:8px;line-height:0}.gemboss-md-imglink:focus-visible{outline:2px solid var(--gemboss-focus, var(--ui-focus, #5661f5));outline-offset:2px}.gemboss-md-img{display:block;max-width:100%;max-height:320px;height:auto;border:1px solid var(--gemboss-border, #e3e3e3);border-radius:8px;background:var(--gemboss-surface-subdued, #f7f7f7);object-fit:contain}.gemboss-md-codeblock{position:relative;margin:0 0 12px;border:1px solid var(--gemboss-border, #e3e3e3);border-radius:8px;background:var(--gemboss-surface-subdued, #f7f7f7);overflow:hidden}.gemboss-md-codelang{display:block;padding:4px 12px 0;color:var(--gemboss-text-subdued, #8a8a8a);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}.gemboss-md-codeblock pre{margin:0;padding:8px 12px;overflow-x:auto}.gemboss-md-codeblock code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5;white-space:pre}.gemboss-md-codemore{display:block;width:100%;padding:6px 12px;border:0;border-top:1px solid var(--gemboss-border, #e3e3e3);background:transparent;color:var(--gemboss-text-subdued, #616161);font-size:12px;text-align:left;cursor:pointer}.gemboss-md-codemore:hover{background:#00000008}.gemboss-narr-row.source{align-items:flex-start}.gemboss-narr-source{min-width:0;flex:1}.gemboss-narr-source-head{font-size:11px;color:var(--gemboss-text-muted, #686b71);margin-bottom:4px}.gemboss-narr-source-head code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gemboss-narr-source-code{margin:0;padding:8px 12px;border-radius:8px;max-height:220px;overflow:auto;background:var(--gemboss-primary-soft, #f2f3f5);border:1px solid var(--gemboss-divider, #e5e7ea);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--gemboss-fs-micro);line-height:17px;white-space:pre;tab-size:2}.gemboss-narr-source-code .c-com{color:#6a7a86;font-style:italic}.gemboss-narr-source-code .c-str{color:#9a3412}.gemboss-narr-source-code .c-num{color:#1d6fa5}.gemboss-narr-source-code .c-kw{color:#7c3aed;font-weight:600}.gemboss-narr-source-code .c-key{color:#0b6b3a}.gemboss-narr-source-code .c-tag{color:#b0197a}.gemboss-narr-source-code .c-attr{color:#7c3aed}.gemboss-narr-source-code .c-pun{color:#6a6d73}@media (max-width: 520px){.gemboss-narr-source-code{max-height:160px;font-size:11px}}.gemboss-narr-dot-quiet{visibility:hidden}
|
package/src/collections.tsx
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* Polaris; same reasoning as ./page). The markup is the same as the plain-HTML contract in the catalog, so a surface
|
|
16
16
|
* without React writes these classes by hand and gets the same thing.
|
|
17
17
|
*/
|
|
18
|
+
import "./collections.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
|
|
18
19
|
import React from "react";
|
|
19
20
|
import { attachBoardMove } from "./board-move";
|
|
20
21
|
|
package/src/dialog.tsx
CHANGED
|
@@ -9,12 +9,10 @@
|
|
|
9
9
|
* sign-in and "Create a new post" open like this (Featurebase does both as popups: Chris 04/10/2026,
|
|
10
10
|
* "signup login là bật ra popup đó nhanh và tiện hơn").
|
|
11
11
|
*
|
|
12
|
-
* `SearchDialog
|
|
13
|
-
*
|
|
14
|
-
* (debounced, the latest answer wins); ↑ ↓ move, Enter opens, Esc closes. Results are links, so a
|
|
15
|
-
* page without JavaScript loses only the popup, never the search itself (`fallbackHref`).
|
|
12
|
+
* `SearchDialog` lives in search-dialog.tsx since 0.23.0: it brings portal.css (its own look), and a
|
|
13
|
+
* surface that only opens a Dialog should not download it.
|
|
16
14
|
*/
|
|
17
|
-
import React, {
|
|
15
|
+
import React, { useEffect, useId, useRef } from "react";
|
|
18
16
|
import { Icon } from "./icons";
|
|
19
17
|
|
|
20
18
|
const cx = (...p: Array<string | false | null | undefined>) => p.filter(Boolean).join(" ");
|
|
@@ -63,133 +61,3 @@ export function Dialog({ open, onClose, title, children, footer, wide = false, c
|
|
|
63
61
|
</dialog>
|
|
64
62
|
);
|
|
65
63
|
}
|
|
66
|
-
|
|
67
|
-
export type SearchItem = { href: string; title: string; meta?: React.ReactNode };
|
|
68
|
-
export type SearchSection = { title: string; items: SearchItem[] };
|
|
69
|
-
|
|
70
|
-
// One constant, not a default `= []`: a fresh array each render, read by an effect, re-ran it forever
|
|
71
|
-
// ("Maximum update depth exceeded", review of 0.7.0 in Chromium).
|
|
72
|
-
const NO_SECTIONS: SearchSection[] = [];
|
|
73
|
-
|
|
74
|
-
export function SearchDialog({ search, initial = NO_SECTIONS, placeholder = "Search…", label = "Search", fallbackHref, shortcut = true, renderItem }: {
|
|
75
|
-
/** Results for a query. Called at most every 150 ms; an answer to an older query is dropped. */
|
|
76
|
-
search: (q: string) => Promise<SearchSection[]>;
|
|
77
|
-
/** What the popup shows before anything is typed (Featurebase: "Trending requests", "Latest updates"). */
|
|
78
|
-
initial?: SearchSection[];
|
|
79
|
-
placeholder?: string;
|
|
80
|
-
label?: string;
|
|
81
|
-
/** Where the topbar button goes without JavaScript (a search page), used as given. */
|
|
82
|
-
fallbackHref?: string;
|
|
83
|
-
/** ⌘K / Ctrl+K and "/" open it. */
|
|
84
|
-
shortcut?: boolean;
|
|
85
|
-
renderItem?: (item: SearchItem) => React.ReactNode;
|
|
86
|
-
}) {
|
|
87
|
-
const [open, setOpen] = useState(false);
|
|
88
|
-
const [q, setQ] = useState("");
|
|
89
|
-
const [sections, setSections] = useState<SearchSection[]>(initial);
|
|
90
|
-
const [active, setActive] = useState(0);
|
|
91
|
-
const [busy, setBusy] = useState(false);
|
|
92
|
-
const ref = useRef<HTMLDialogElement>(null);
|
|
93
|
-
const input = useRef<HTMLInputElement>(null);
|
|
94
|
-
const seq = useRef(0);
|
|
95
|
-
const listId = useId();
|
|
96
|
-
const flat = sections.flatMap((s) => s.items);
|
|
97
|
-
// The latest `search` and `initial`, read when needed: a consumer's inline arrow or array (a new one
|
|
98
|
-
// each render) must not restart the debounce or the effect.
|
|
99
|
-
const searchRef = useRef(search);
|
|
100
|
-
const initialRef = useRef(initial);
|
|
101
|
-
searchRef.current = search;
|
|
102
|
-
initialRef.current = initial;
|
|
103
|
-
|
|
104
|
-
const show = useCallback(() => {
|
|
105
|
-
const d = ref.current;
|
|
106
|
-
if (d && !d.open) { d.showModal(); setOpen(true); requestAnimationFrame(() => input.current?.focus()); }
|
|
107
|
-
}, []);
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
if (!shortcut) return undefined;
|
|
110
|
-
const onKey = (e: KeyboardEvent) => {
|
|
111
|
-
const t = e.target as HTMLElement | null;
|
|
112
|
-
const typing = !!t && (t.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName));
|
|
113
|
-
// A handler that already took the key (the admin's own ⌘K palette) keeps it.
|
|
114
|
-
if (e.defaultPrevented) return;
|
|
115
|
-
if ((e.key === "k" && (e.metaKey || e.ctrlKey)) || (e.key === "/" && !typing)) { e.preventDefault(); show(); }
|
|
116
|
-
};
|
|
117
|
-
document.addEventListener("keydown", onKey);
|
|
118
|
-
return () => document.removeEventListener("keydown", onKey);
|
|
119
|
-
}, [shortcut, show]);
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
if (!open) return undefined;
|
|
122
|
-
const query = q.trim();
|
|
123
|
-
// Every change takes a new number: an answer still on its way for an older query is dropped,
|
|
124
|
-
// including when the box was just cleared (it used to land under an empty box).
|
|
125
|
-
const mine = ++seq.current;
|
|
126
|
-
if (!query) { setSections(initialRef.current); setActive(0); setBusy(false); return undefined; }
|
|
127
|
-
setBusy(true);
|
|
128
|
-
const t = setTimeout(async () => {
|
|
129
|
-
try {
|
|
130
|
-
const res = await searchRef.current(query);
|
|
131
|
-
if (mine === seq.current) { setSections(res); setActive(0); }
|
|
132
|
-
} catch {
|
|
133
|
-
if (mine === seq.current) setSections(NO_SECTIONS);
|
|
134
|
-
} finally {
|
|
135
|
-
if (mine === seq.current) setBusy(false);
|
|
136
|
-
}
|
|
137
|
-
}, 150);
|
|
138
|
-
return () => { clearTimeout(t); if (mine === seq.current) setBusy(false); };
|
|
139
|
-
}, [q, open]);
|
|
140
|
-
// Before anything is typed, show the latest suggestions the page passed.
|
|
141
|
-
useEffect(() => { if (open && !q.trim()) setSections(initial); }, [initial, open, q]);
|
|
142
|
-
// The highlighted result stays in view as the arrows move it.
|
|
143
|
-
useEffect(() => {
|
|
144
|
-
if (!open) return;
|
|
145
|
-
document.getElementById(`${listId}-${active}`)?.scrollIntoView({ block: "nearest" });
|
|
146
|
-
}, [active, open, listId]);
|
|
147
|
-
|
|
148
|
-
const go = (item: SearchItem | undefined) => { if (item) window.location.assign(item.href); };
|
|
149
|
-
let n = -1;
|
|
150
|
-
return (
|
|
151
|
-
<>
|
|
152
|
-
<a className="gb-search-trigger" href={fallbackHref ?? "#"} aria-label={label} aria-haspopup="dialog"
|
|
153
|
-
onClick={(e) => { e.preventDefault(); show(); }}>
|
|
154
|
-
<Icon name="search" size={18} />
|
|
155
|
-
</a>
|
|
156
|
-
<dialog ref={ref} className="ui-modal gb-search" aria-label={label}
|
|
157
|
-
onClose={() => { setOpen(false); setQ(""); }}
|
|
158
|
-
onClick={(e) => { if (e.target === e.currentTarget) e.currentTarget.close(); }}>
|
|
159
|
-
<div className="gb-search-box">
|
|
160
|
-
<Icon name="search" size={18} className="gb-search-icon" />
|
|
161
|
-
<input ref={input} className="gb-search-input" type="search" placeholder={placeholder} aria-label={label}
|
|
162
|
-
value={q} onChange={(e) => setQ(e.target.value)} role="combobox" aria-expanded="true" aria-controls={listId}
|
|
163
|
-
aria-activedescendant={flat[active] ? `${listId}-${active}` : undefined} autoComplete="off"
|
|
164
|
-
onKeyDown={(e) => {
|
|
165
|
-
if (e.key === "ArrowDown") { e.preventDefault(); setActive((a) => Math.min(a + 1, flat.length - 1)); }
|
|
166
|
-
else if (e.key === "ArrowUp") { e.preventDefault(); setActive((a) => Math.max(a - 1, 0)); }
|
|
167
|
-
// Enter that confirms an IME composition (Vietnamese, Chinese) is not "open".
|
|
168
|
-
else if (e.key === "Enter" && !e.nativeEvent.isComposing && e.keyCode !== 229) { e.preventDefault(); go(flat[active]); }
|
|
169
|
-
}} />
|
|
170
|
-
</div>
|
|
171
|
-
<p className="gb-search-empty" aria-live="polite">
|
|
172
|
-
{sections.every((s) => !s.items.length) && q.trim() ? (busy ? "Searching…" : "Nothing matches.") : ""}
|
|
173
|
-
</p>
|
|
174
|
-
<div className="gb-search-results" id={listId} role="listbox" aria-busy={busy}>
|
|
175
|
-
{sections.filter((s) => s.items.length).map((s) => (
|
|
176
|
-
<div key={s.title} className="gb-search-section" role="group" aria-label={s.title}>
|
|
177
|
-
<div className="gb-search-section-title">{s.title}</div>
|
|
178
|
-
{s.items.map((it) => {
|
|
179
|
-
n += 1;
|
|
180
|
-
const i = n;
|
|
181
|
-
return (
|
|
182
|
-
<a key={`${s.title}-${it.href}`} id={`${listId}-${i}`} href={it.href} role="option" aria-selected={i === active}
|
|
183
|
-
className={cx("gb-search-item", i === active && "is-active")} onMouseMove={() => setActive(i)}>
|
|
184
|
-
{renderItem ? renderItem(it) : (<><span className="gb-search-item-title">{it.title}</span>{it.meta ? <span className="gb-search-item-meta">{it.meta}</span> : null}</>)}
|
|
185
|
-
</a>
|
|
186
|
-
);
|
|
187
|
-
})}
|
|
188
|
-
</div>
|
|
189
|
-
))}
|
|
190
|
-
</div>
|
|
191
|
-
<div className="gb-search-foot" aria-hidden="true"><span>↵ open</span><span>↑↓ move</span><span>esc</span></div>
|
|
192
|
-
</dialog>
|
|
193
|
-
</>
|
|
194
|
-
);
|
|
195
|
-
}
|
package/src/editor/controls.tsx
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// · the slider commits on every change (its number);
|
|
11
11
|
// · the edge box hands each keystroke to the caller (`onChange(side, raw)`) and says when to commit (`onCommit`, on
|
|
12
12
|
// blur): the caller decides what an empty edge means, and the admin has three answers to that on purpose.
|
|
13
|
+
import "../editor.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
|
|
13
14
|
import { useEffect, useState } from "react";
|
|
14
15
|
import type React from "react";
|
|
15
16
|
import { cssUrl } from "./css-url";
|
package/src/editor/frame.tsx
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// by the plugin editor and the studio canvas, so together they ride in the chunk the toggle already had in the admin.
|
|
4
4
|
// Split into one module per piece, the admin build grew a lazy chunk to place them (its runtime +52 bytes, every
|
|
5
5
|
// screen's first load +20 B brotli). Measured 06/10/2026.
|
|
6
|
+
import "../editor.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
|
|
6
7
|
import type React from "react";
|
|
7
8
|
|
|
8
9
|
/** Which half a phone shows (≤760px shows one at a time; wider shows both). Values are the CSS's `data-mobile-pane`. */
|
|
@@ -197,6 +198,16 @@ export function PhoneGlyph({ size = 15 }: { size?: number }) {
|
|
|
197
198
|
);
|
|
198
199
|
}
|
|
199
200
|
|
|
201
|
+
/** A tablet: a wider slate than the phone, so the two read apart at 15px. Exported 0.26.0 for the funnel canvas's
|
|
202
|
+
* "All sizes" (desktop, tablet and phone side by side); the device toggle below draws the same one. */
|
|
203
|
+
export function TabletGlyph({ size = 15 }: { size?: number }) {
|
|
204
|
+
return (
|
|
205
|
+
<svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
206
|
+
<rect x="4" y="3" width="16" height="18" rx="2" /><line x1="10.5" y1="18" x2="13.5" y2="18" />
|
|
207
|
+
</svg>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
200
211
|
/** Desktop / tablet / mobile preview toggle. The kit's segmented control (`.ui-seg`, 06/10/2026), the same look as every
|
|
201
212
|
* other switch in the editors; `.gemboss-pv-devices` / `.gemboss-pv-device` stay as the hooks editor-plain.js finds. */
|
|
202
213
|
export function DeviceToggle({ device, onChange }: { device: PreviewBreakpoint; onChange: (device: PreviewBreakpoint) => void }) {
|
|
@@ -221,10 +232,7 @@ export function DeviceToggle({ device, onChange }: { device: PreviewBreakpoint;
|
|
|
221
232
|
aria-pressed={device === "tablet"}
|
|
222
233
|
onClick={() => onChange("tablet")}
|
|
223
234
|
>
|
|
224
|
-
|
|
225
|
-
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
226
|
-
<rect x="4" y="3" width="16" height="18" rx="2" /><line x1="10.5" y1="18" x2="13.5" y2="18" />
|
|
227
|
-
</svg>
|
|
235
|
+
<TabletGlyph />
|
|
228
236
|
</button>
|
|
229
237
|
<button
|
|
230
238
|
type="button"
|
package/src/editor/index.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* here holds state.
|
|
25
25
|
*/
|
|
26
26
|
export {
|
|
27
|
-
DeviceToggle, EditorBack, EditorFrame, EditorSaveState, EditorTopbar, MonitorGlyph, PhoneGlyph,
|
|
27
|
+
DeviceToggle, EditorBack, EditorFrame, EditorSaveState, EditorTopbar, MonitorGlyph, PhoneGlyph, TabletGlyph,
|
|
28
28
|
type EditorFrameProps, type EditorPane, type EditorSplit, type EditorTopbarProps, type EditorTopbarVariant, type PreviewBreakpoint,
|
|
29
29
|
} from "./frame";
|
|
30
30
|
export { EditorChatToggle, EditorPaneTabs } from "./panes";
|
|
@@ -41,3 +41,12 @@ export {
|
|
|
41
41
|
} from "./controls";
|
|
42
42
|
export { swatchState, type SwatchState } from "./swatch";
|
|
43
43
|
export { cssUrl } from "./css-url";
|
|
44
|
+
// Step 4 (0.22.0): the page's layers and the drawer (`layers`, stateless; the page editor draws them), a list whose rows
|
|
45
|
+
// reorder (`sortable`, "use client": a drag holds state; no admin screen uses it), and the element outline (`tree`, the
|
|
46
|
+
// inspector's). Same rule: grouped by who draws what.
|
|
47
|
+
export {
|
|
48
|
+
EditorDrawer, LayerList, layerName,
|
|
49
|
+
type EditorDrawerProps, type LayerItem, type LayerListProps,
|
|
50
|
+
} from "./layers";
|
|
51
|
+
export { SortableLayerList, type SortableLayerListProps } from "./sortable";
|
|
52
|
+
export { LayerTree, type LayerTreeProps, type LayerTreeRow } from "./tree";
|