@gemboss/ui 0.40.0 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +110 -0
- package/README.md +98 -2
- package/catalog/editor.html +9 -7
- package/catalog/index.html +394 -235
- package/gemboss-ui.css +3 -3
- package/package.json +6 -2
- package/parts/components.css +1 -1
- package/parts/core.css +1 -1
- package/parts/shell.css +2 -2
- package/src/editor/controls.tsx +52 -8
- package/src/editor/index.ts +2 -2
- package/src/editor/repeater.tsx +27 -19
- package/src/editor/swatch.ts +133 -9
- package/src/editor-plain.js +1 -1
- package/src/editor.css +1 -1
- package/src/index.ts +3 -2
- package/src/portal.tsx +12 -6
- package/src/reactions-data.ts +13 -0
- package/src/reactions.tsx +5 -5
- package/src/reader-dialog.css +1 -0
- package/src/reader-dialog.tsx +26 -0
- package/src/shell.css +1 -1
- package/src/team-chat-data.ts +46 -13
- package/src/team-chat-plain.js +1 -0
package/src/reactions.tsx
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* count does not), the viewer's own outlined and filled (not only coloured: two chips that differ only in hue look the
|
|
11
11
|
* same to a colour-blind reader). No chips, no row.
|
|
12
12
|
* - "Add reaction": opens the picker IN FLOW under the row (not floating: a layer in a scrolling column has to fight the
|
|
13
|
-
* bottom edge; a row in flow is scrolled to by the browser). Frequently used first (this browser's,
|
|
14
|
-
*
|
|
13
|
+
* bottom edge; a row in flow is scrolled to by the browser). Frequently used first (this browser's, filled up to nine
|
|
14
|
+
* with SUGGESTED_REACTIONS), then the groups; search by words; arrows move in the grid, Enter in the search picks the first, Escape closes
|
|
15
15
|
* and gives focus back to the button.
|
|
16
16
|
*
|
|
17
17
|
* Each target is 44px (a control, CLAUDE.md §9.1) while the visible pill is 26px: transparent padding carries the rest,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import "./reactions.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
|
|
21
21
|
import React, { useEffect, useId, useRef, useState } from "react";
|
|
22
22
|
import { Icon } from "./icons";
|
|
23
|
-
import {
|
|
23
|
+
import { frequentReactions, REACTION_GROUPS, reactionLabel, reactionWords, searchReactions, type Reaction } from "./reactions-data";
|
|
24
24
|
|
|
25
25
|
const RECENT_KEY = "gemboss-ui:reactions-recent";
|
|
26
26
|
const RECENT_MAX = 9;
|
|
@@ -91,11 +91,11 @@ export function Reactions({ items, onToggle, target = "this", canReact = true, o
|
|
|
91
91
|
|
|
92
92
|
export function ReactionPicker({ items, onPick, onClose, id }: { items: readonly Reaction[]; onPick: (emoji: string) => void; onClose: () => void; id?: string }) {
|
|
93
93
|
const [q, setQ] = useState("");
|
|
94
|
-
const [recent, setRecent] = useState<readonly string[]>(
|
|
94
|
+
const [recent, setRecent] = useState<readonly string[]>(() => frequentReactions([]));
|
|
95
95
|
const search = useRef<HTMLInputElement>(null);
|
|
96
96
|
const body = useRef<HTMLDivElement>(null);
|
|
97
97
|
// Storage is read after mount: the server render and the first client render must draw the same picker.
|
|
98
|
-
useEffect(() => { const r = readRecent(); if (r.length) setRecent(r); search.current?.focus(); }, []);
|
|
98
|
+
useEffect(() => { const r = readRecent(); if (r.length) setRecent(frequentReactions(r)); search.current?.focus(); }, []);
|
|
99
99
|
const mine = (e: string) => items.some((r) => r.emoji === e && r.mine);
|
|
100
100
|
const btn = (e: string) => (
|
|
101
101
|
<button key={e} type="button" className="ui-reaction-picker__btn" title={reactionWords(e).split(" ")[0] || e}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dialog.ui-modal.ui-reader{padding:0;box-sizing:border-box;width:min(1440px,94vw);max-width:100%;height:min(92dvh,1200px);max-height:100dvh}dialog.ui-modal.ui-reader[open]{display:flex;flex-direction:column}dialog.ui-modal.ui-reader>.ui-modal__head{flex:none;flex-wrap:wrap;row-gap:8px}dialog.ui-modal.ui-reader>.ui-modal__head>.ui-modal__title{flex:1 1 0;min-width:min(100%,220px)}dialog.ui-modal.ui-reader>.ui-modal__foot{flex:none}dialog.ui-modal.ui-reader>.ui-modal__body{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;padding:0;overflow:auto;overscroll-behavior:contain}dialog.ui-modal.ui-reader .ui-reader__frame{display:block;flex:1 1 auto;width:100%;min-height:0;border:0}dialog.ui-modal.ui-reader .ui-reader__scroll{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;padding:24px 32px 48px}dialog.ui-modal.ui-reader .ui-reader__scroll:focus{outline:none}@media (max-width: 47.9975em){dialog.ui-modal.ui-reader{width:100%;height:100dvh;border:0;border-radius:0}dialog.ui-modal.ui-reader>.ui-modal__head>.ui-modal__actions{order:3;flex-basis:100%}dialog.ui-modal.ui-reader .ui-reader__scroll{padding:16px 16px 40px}}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ReaderDialog — @gemboss/ui 0.41.0. The kit popup sized for READING a document over the list it came from: a doc, a
|
|
5
|
+
* brief, a report. Two surfaces drew it with their own CSS the same week, because Dialog's widths (460, `wide` 620) are a
|
|
6
|
+
* form's: GemMedia's admin Docs (gemmedia #76, `dialog.ui-modal.md-docpop`) and partner-radar's Docs (gemlabs #1122,
|
|
7
|
+
* `dialog.ui-modal.pr-docpop`), both near the whole window and the whole screen on a phone. Chris 20/10/2026: "làm đi"
|
|
8
|
+
* (put it in the kit).
|
|
9
|
+
*
|
|
10
|
+
* It IS `Dialog` (dialog.tsx), same markup and behaviour, with `ui-reader` on it: reader-dialog.css sizes it, wraps the
|
|
11
|
+
* head (the actions drop under the title on a phone), and makes the body a column with no padding for the document to
|
|
12
|
+
* fill. What fills it is the surface's: an `<iframe class="ui-reader__frame">` (a self-contained HTML doc), or a scroller
|
|
13
|
+
* of its own with `ui-reader__scroll` (padded, scrolls, keeps its overscroll). Either way the page behind holds still.
|
|
14
|
+
*/
|
|
15
|
+
import "./reader-dialog.css";
|
|
16
|
+
import React from "react";
|
|
17
|
+
import { Dialog, type DialogProps } from "./dialog";
|
|
18
|
+
|
|
19
|
+
const cx = (...p: Array<string | false | null | undefined>) => p.filter(Boolean).join(" ");
|
|
20
|
+
|
|
21
|
+
/** Dialog's props, less `wide`: the reader has one size. */
|
|
22
|
+
export type ReaderDialogProps = Omit<DialogProps, "wide">;
|
|
23
|
+
|
|
24
|
+
export function ReaderDialog({ className, ...rest }: ReaderDialogProps) {
|
|
25
|
+
return <Dialog {...rest} className={cx("ui-reader", className)} />;
|
|
26
|
+
}
|
package/src/shell.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gemboss-popover-surface{background:var(--gemboss-surface);background:color-mix(in srgb,var(--gemboss-surface) 93%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.4);backdrop-filter:blur(14px) saturate(1.4);border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-lg);box-shadow:var(--gemboss-shadow-raised)}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.gemboss-popover-surface{background:var(--gemboss-surface)}}.icon-nav{position:fixed;top:56px;left:0;z-index:200;width:72px;height:calc(100dvh - 56px);background:var(--gemboss-rail-bg);border-right:1px solid var(--gemboss-divider);display:flex;flex-direction:column;padding-top:8px;overflow:hidden}.gemboss-account-menu{position:absolute;top:calc(100% + 6px);right:0;min-width:220px;z-index:320;overflow:hidden}.gemboss-account-menu-item,.ui-menu__item{display:block;width:100%;min-height:44px;padding:12px 16px;border:0;background:transparent;font:inherit;font-size:13px;color:var(--gemboss-text);text-align:left;text-decoration:none;cursor:pointer;transition:background var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gemboss-account-menu-item:hover,.ui-menu__item:hover{background:var(--gemboss-hover)}.gemboss-account-menu-item:focus-visible,.ui-menu__item:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:-2px;background:var(--gemboss-hover)}.gemboss-account-menu-item.danger,.ui-menu__item--danger{color:var(--gemboss-danger-strong)}.gemboss-account-chip{width:30px;height:30px;border:1px solid #cfd6ce;border-radius:var(--gemboss-radius-full);background:#f5f7f4;color:#303633;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:11px;font-weight:700;cursor:pointer}.gemboss-platform-main{box-sizing:border-box;min-height:100dvh;margin-left:72px;padding-top:56px;background:var(--gemboss-app-bg)}.icon-nav{top:56px;height:calc(100dvh - 56px);background:var(--gemboss-nav-bg);border-right-color:var(--gemboss-divider)}@media (max-width: 1040px){.gemboss-platform-topbar{grid-template-columns:minmax(120px,1fr) minmax(220px,520px) minmax(120px,1fr)}}@media (max-width: 760px){.gemboss-platform-main{margin-left:0}}.gemboss-account-chip{width:32px;height:32px;border-radius:50%;background:var(--gemboss-primary);color:#fff;font-weight:600;font-size:12px;display:inline-flex;align-items:center;justify-content:center;border:none;cursor:pointer;transition:transform var(--gemboss-transition-base) ease}.gemboss-account-chip:hover{transform:scale(1.05)}.gemboss-account-chip:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gemboss-platform-main{margin-top:56px;margin-left:72px;min-height:calc(100vh - 56px);padding:24px;background:#fafafb}@media (max-width: 768px){.gemboss-platform-main{margin-left:0;padding:16px}}.gemboss-platform-shell{display:block;min-height:100vh;background:var(--gemboss-app-bg)}.gemboss-platform-topbar{position:fixed;inset:0 0 auto;z-index:300;height:56px;border-bottom:1px solid var(--gemboss-divider);background:var(--gemboss-topbar-bg);display:grid;grid-template-columns:minmax(200px,1fr) minmax(280px,560px) minmax(200px,1fr);align-items:center;gap:16px;padding:0 16px;box-shadow:var(--gemboss-shadow-resting)}:root:has(.gemboss-platform-topbar){scroll-padding-top:64px}.gemboss-account-chip{width:32px;height:32px;border:1px solid var(--gemboss-chip-line);border-radius:var(--gemboss-radius-full);background:var(--gemboss-surface);color:var(--gemboss-chip-ink);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:11px;font-weight:700;cursor:pointer;transition:border-color var(--gemboss-transition-base) ease,background-color var(--gemboss-transition-base) ease}.gemboss-account-chip:hover{border-color:var(--gemboss-chip-line-hover);background:var(--gemboss-chip-bg-hover);transform:none}.icon-nav{position:fixed;top:56px;left:0;z-index:200;width:72px;height:calc(100dvh - 56px);border-right:1px solid var(--gemboss-divider);background:var(--gemboss-nav-bg);padding-top:12px}.gemboss-platform-main{min-height:calc(100vh - 56px);margin-top:56px;margin-left:72px;background:var(--gemboss-app-bg);padding:24px}@media (max-width: 1120px){.gemboss-platform-topbar{grid-template-columns:220px minmax(220px,1fr) auto;gap:12px}}@media (max-width: 760px){.gemboss-platform-topbar{height:auto;min-height:56px;grid-template-columns:minmax(0,1fr) auto;padding:12px}.gemboss-account-chip,.icon-nav{display:none}.gemboss-platform-main{margin-left:0;padding:16px}}.gnav-scroll{scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-assistant-railfoot.is-button{width:100%;border:none;background:none;cursor:pointer;text-align:left;font:inherit;border-radius:8px;transition:background .12s ease,color .12s ease}.gemboss-assistant-railfoot.is-button:hover{background:var(--gemboss-primary-soft);color:var(--gemboss-primary-dark)}.gemboss-assistant-empty{padding:24px 20px;color:var(--gemboss-text-muted);font-size:13px}@media (max-width: 760px){.gemboss-platform-topbar{display:flex;align-items:center;gap:8px;height:56px;min-height:56px;padding:0 12px}.gemboss-account-chip{display:inline-flex}.gemboss-platform-main{padding-top:16px;padding-bottom:calc(56px + env(safe-area-inset-bottom))}}@media (pointer: coarse){.gemboss-account-chip{width:44px;height:44px}.gnav-item{min-height:44px}.gemboss-assistant-collapse,.gemboss-assistant-newchat{min-height:44px;min-width:44px}}.icon-nav{width:240px;padding:12px 0 0;overflow:hidden;background:var(--gemboss-nav-bg);display:flex;flex-direction:column}.gnav-scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding-inline:12px}.gnav-bottom{padding:0 12px 12px}.gnav-item{display:flex;align-items:center;gap:12px;width:100%;padding:8px 12px;margin:1px 0;border:0;background:transparent;cursor:pointer;text-align:left;border-radius:var(--gemboss-radius-md);text-decoration:none;font-family:inherit;color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:500;line-height:1.2;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gnav-item:hover{background:var(--gemboss-nav-hover)}.gnav-item:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gnav-item.active{color:var(--gemboss-active-fg);font-weight:600}.gnav-group:not(.has-active-child)>.gnav-item.active{background:var(--gemboss-active-bg)}.gnav-group:not(.has-active-child)>.gnav-item.active:hover{background:var(--gemboss-active-bg)}.gnav-group.has-active-child>.gnav-item.active:hover{background:var(--gemboss-nav-hover)}.gnav-ico{flex:0 0 20px;width:20px;height:20px;display:grid;place-items:center}.gnav-ico svg{width:20px;height:20px;fill:currentColor}.gnav-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gnav-sub{list-style:none;margin:1px 0 6px;padding:0}.gnav-subitem{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 12px 6px 44px;margin:1px 0;border-radius:var(--gemboss-radius-sm);color:var(--gemboss-text-muted);font-size:13px;line-height:1.2;text-decoration:none;white-space:nowrap;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}@media (pointer: coarse){.gnav-subitem{min-height:44px}}.gnav-subitem:hover{background:var(--gemboss-nav-hover);color:var(--gemboss-text)}.gnav-subitem.active{color:var(--gemboss-active-fg);font-weight:600;background:var(--gemboss-active-bg)}.gnav-subitem.active:hover{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gnav-subitem.active:before{content:"";position:absolute;left:20px;top:50%;transform:translateY(-50%);width:3px;height:15px;border-radius:2px;background:var(--gemboss-primary)}.gnav-subitem.is-soon{opacity:.5;cursor:default}.gnav-subitem em{font-style:normal;font-size:var(--gemboss-fs-micro);font-weight:600;letter-spacing:.04em;text-transform:uppercase;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-sm);padding:1px 6px}.gnav-sep{height:1px;background:var(--gemboss-divider);margin:8px 6px}.gnav-item.gnav-assistant{color:var(--gemboss-accent-strong);font-weight:600;background:var(--gemboss-accent-soft)}.gnav-item.gnav-assistant .gnav-ico svg{fill:var(--gemboss-accent)}.gnav-item.gnav-assistant:hover{background:color-mix(in srgb,var(--gemboss-accent) 16%,var(--gemboss-surface))}.gnav-item.gnav-assistant.active{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gnav-item.gnav-assistant.active .gnav-ico svg{fill:var(--gemboss-active-fg)}.gemboss-platform-main{margin-left:240px}.gemboss-mobile-menu-btn,.gemboss-mobile-nav-backdrop{display:none}@media (max-width: 760px){.gemboss-platform-main{margin-left:0;padding-bottom:env(safe-area-inset-bottom)}.gemboss-mobile-menu-btn{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:38px;height:38px;margin-left:-2px;border:0;border-radius:8px;background:transparent;cursor:pointer;color:var(--gemboss-text)}.gemboss-mobile-menu-btn:active{background:var(--gemboss-hover)}.icon-nav{display:flex;width:min(82vw,300px);transform:translate(-100%);transition:transform .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:none}.gemboss-platform-shell.is-mobile-nav-open .icon-nav{transform:translate(0);box-shadow:2px 0 26px #1f1e1d33}.gemboss-mobile-nav-backdrop{display:block;position:fixed;inset:56px 0 0;width:100%;border:0;padding:0;background:#14131261;opacity:0;pointer-events:none;transition:opacity .22s ease;z-index:999}.gemboss-platform-shell.is-mobile-nav-open .gemboss-mobile-nav-backdrop{opacity:1;pointer-events:auto}}@media (max-width: 305.98px){.gemboss-platform-topbar{padding:0 8px}}@media (min-width: 306px) and (max-width: 460px){.gemboss-platform-topbar{padding:0 8px}.gemboss-mobile-menu-btn,.gemboss-account-chip{width:44px;height:44px}}.gemboss-assistant-chatslot{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0}.gemboss-assistant-chatslot[hidden]{display:none}.gemboss-assistant-page>.gemboss-assistant-tabs{flex:0 0 auto;display:flex;align-items:center;gap:4px;padding:4px 8px 0;overflow-x:auto;scrollbar-width:none}.gemboss-assistant-tabs::-webkit-scrollbar{display:none}.gemboss-assistant-tab{display:flex;align-items:center;flex:0 1 auto;min-width:0;max-width:190px;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-md);background:transparent}.gemboss-assistant-tab.active{background:var(--gemboss-active-bg);border-color:var(--gemboss-active-bg)}.gemboss-assistant-tab-main{display:flex;align-items:center;gap:6px;min-width:0;min-height:44px;padding:0 4px 0 8px;border:0;background:transparent;font:inherit;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted);cursor:pointer}.gemboss-assistant-tab.active .gemboss-assistant-tab-main{color:var(--gemboss-text-strong)}.gemboss-assistant-tab-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gemboss-assistant-tab-dot{flex:0 0 auto;width:6px;height:6px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-divider)}.gemboss-assistant-tab-dot.is-running{background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}.gemboss-assistant-tab-close{flex:0 0 auto;width:44px;height:44px;display:grid;place-items:center;border:0;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;padding:0}.gemboss-assistant-tab-close:hover{color:var(--gemboss-text-strong)}.gemboss-assistant-tab-close svg{width:14px;height:14px}.gemboss-assistant-sronly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.gemboss-assistant-thread-running{flex:0 0 auto;width:6px;height:6px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}@media (prefers-reduced-motion: reduce){.gemboss-assistant-tab-dot.is-running,.gemboss-assistant-thread-running{animation:none}}.gemboss-assistant-route-claim{display:block;height:100%}.gemboss-assistant-layout.is-dock{height:auto;min-height:0}.gemboss-assistant-layout.is-dock .gemboss-assistant-page{height:auto;max-width:none;padding:4px 0 8px}.gnav-item.gnav-assistant{position:relative}body.gemboss-assistant-busy .gnav-item.gnav-assistant:after,body.gemboss-assistant-unread .gnav-item.gnav-assistant:after{content:"";position:absolute;top:6px;left:26px;width:8px;height:8px;border-radius:50%;border:2px solid var(--gemboss-surface)}body.gemboss-assistant-busy .gnav-item.gnav-assistant:after{background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}body.gemboss-assistant-unread .gnav-item.gnav-assistant:after{background:var(--gemboss-success-strong)}@media (prefers-reduced-motion: reduce){body.gemboss-assistant-busy .gnav-item.gnav-assistant:after{animation:none}}.gemboss-assistant-layout{display:flex;height:calc(100dvh - 56px);width:100%;min-height:0}.gemboss-assistant-rail{flex:0 0 264px;width:264px;display:flex;flex-direction:column;min-height:0;border-right:1px solid var(--gemboss-divider);background:transparent;padding:16px 12px 12px;gap:12px;transition:flex-basis .18s ease,width .18s ease}.gemboss-assistant-rail-top{display:flex;align-items:center;gap:6px}.gemboss-assistant-newchat{display:flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0;padding:12px;border:1px solid var(--gemboss-divider);border-radius:12px;background:transparent;color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:600;cursor:pointer;transition:background .12s ease,border-color .12s ease}.gemboss-assistant-newchat:hover{background:#00000009;border-color:var(--gemboss-text-muted)}.gemboss-assistant-newchat svg{width:17px;height:17px;fill:currentColor;flex:0 0 auto}.gemboss-assistant-newchat span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1 1 auto}.gemboss-assistant-kbd{flex:0 0 auto;font-size:var(--gemboss-fs-micro);font-weight:600;line-height:1;padding:4px 6px;border:1px solid var(--gemboss-divider);border-radius:6px;background:transparent;color:var(--gemboss-text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gemboss-assistant-search:focus-within .gemboss-assistant-kbd{display:none}.gemboss-assistant-collapse{flex:0 0 auto;display:grid;place-items:center;width:34px;height:34px;border:0;border-radius:8px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.gemboss-assistant-collapse:hover{background:#0000000d;color:var(--gemboss-text)}.gemboss-assistant-collapse svg{width:16px;height:16px;fill:currentColor}.gemboss-assistant-search{gap:6px}.gemboss-assistant-search>svg{width:15px;height:15px;fill:var(--gemboss-text-muted);flex:0 0 auto}.gemboss-assistant-search-clear{display:grid;place-items:center;width:20px;height:20px;border:0;border-radius:6px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer}.gemboss-assistant-search-clear:hover{background:#00000012;color:var(--gemboss-text)}.gemboss-assistant-search-clear svg{width:13px;height:13px;fill:currentColor}.gemboss-assistant-railfoot{flex:0 0 auto;display:flex;align-items:center;gap:6px;padding:8px 12px 2px;border-top:1px solid var(--gemboss-divider);margin-top:4px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption);line-height:1.35}.gemboss-assistant-railfoot svg{width:13px;height:13px;flex:0 0 auto;fill:currentColor;opacity:.8}.gemboss-assistant-threads{flex:1 1 auto;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:2px}.gemboss-assistant-threads-empty{padding:16px 8px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption)}.gemboss-assistant-group{display:flex;flex-direction:column;gap:2px}.gemboss-assistant-group+.gemboss-assistant-group{margin-top:12px}.gemboss-assistant-group-label{padding:4px 12px;font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--gemboss-text-muted);text-transform:uppercase}.gemboss-assistant-thread{position:relative;display:flex;align-items:center;border-radius:8px;transition:background .12s ease}.gemboss-assistant-thread:hover{background:var(--gemboss-hover, rgba(0,0,0,.04))}.gemboss-assistant-thread.active{background:#00000012}.gemboss-assistant-thread-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 12px;border:0;background:transparent;text-align:left;cursor:pointer}.gemboss-assistant-thread-titlerow{display:flex;align-items:center;gap:6px;width:100%;min-width:0}.gemboss-assistant-pin-dot{width:12px;height:12px;flex:0 0 auto;fill:var(--gemboss-text-muted)}.gemboss-assistant-thread-title{flex:1 1 auto;min-width:0;font-size:13px;font-weight:500;color:var(--gemboss-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gemboss-assistant-thread-meta{font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-assistant-thread.menu-open{background:#00000012}.gemboss-assistant-thread.menu-open .gemboss-assistant-thread-actions{opacity:1}.gemboss-assistant-menu{z-index:60;width:184px;padding:6px;display:flex;flex-direction:column}.gemboss-assistant-menu-confirm{padding:8px 12px 6px;font-size:var(--gemboss-fs-caption);font-weight:600;color:var(--gemboss-text)}.gemboss-assistant-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;border-radius:8px;background:transparent;text-align:left;font-size:13px;color:var(--gemboss-text);cursor:pointer}.gemboss-assistant-menu button:hover{background:var(--gemboss-hover, rgba(0,0,0,.05))}.gemboss-assistant-menu button.danger{color:var(--gemboss-danger-strong)}.gemboss-assistant-menu button svg{width:15px;height:15px;fill:currentColor;flex:0 0 auto}.gemboss-assistant-thread-actions{position:absolute;right:6px;display:flex;gap:2px;opacity:0;transition:opacity .12s ease}.gemboss-assistant-thread:hover .gemboss-assistant-thread-actions,.gemboss-assistant-thread:focus-within .gemboss-assistant-thread-actions{opacity:1}.gemboss-assistant-thread-act{display:grid;place-items:center;width:26px;height:26px;border:0;border-radius:8px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.gemboss-assistant-thread-act:hover{background:#00000012;color:var(--gemboss-text)}.gemboss-assistant-thread-act.danger:hover{color:var(--gemboss-danger-strong)}.gemboss-assistant-thread-act svg{width:15px;height:15px;fill:currentColor}.gemboss-assistant-thread.editing{background:#00000012}.gemboss-assistant-thread-edit{display:flex;align-items:center;gap:2px;width:100%;padding:6px}.gemboss-assistant-thread-edit input{flex:1 1 auto;min-width:0}.gemboss-assistant-layout .gemboss-assistant-page{height:100%;max-width:820px;flex:1 1 auto;min-width:0;padding-top:16px}.gemboss-assistant-layout .gemboss-assistant-page.is-switching{opacity:.55;transition:opacity .12s ease;pointer-events:none}.gemboss-assistant-rail.is-collapsed{flex-basis:60px;width:60px;padding:16px 8px 12px}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-rail-top{flex-direction:column;gap:8px}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-newchat{justify-content:center;padding:8px;flex:0 0 auto}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-newchat span,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-search,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-railfoot,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-threads{display:none}@media (max-width: 760px){.gemboss-assistant-rail{flex-basis:60px;width:60px;padding:16px 8px 12px}.gemboss-assistant-rail .gemboss-assistant-rail-top{flex-direction:column;gap:8px}.gemboss-assistant-newchat{justify-content:center;padding:8px;flex:0 0 auto}.gemboss-assistant-newchat span,.gemboss-assistant-search,.gemboss-assistant-railfoot,.gemboss-assistant-threads,.gemboss-assistant-collapse{display:none}}.gemboss-assistant-page{height:calc(100dvh - 56px);width:100%;max-width:760px;margin:0 auto;padding:24px 0 16px;display:flex;flex-direction:column;min-height:0}.gemboss-assistant-page>*{flex:1 1 auto;min-height:0}.gemboss-assistant-empty{flex:1;display:grid;place-items:center;color:var(--gemboss-text-muted);font-size:14px}.gemboss-platform-shell{display:flow-root}.gemboss-platform-main{padding-bottom:calc(24px + var(--gemboss-invite-h, 0px))}@keyframes gemboss-assistant-pulse{0%,to{opacity:1}50%{opacity:.35}}.gb-account{position:relative}.gb-account>summary{list-style:none}.gb-account>summary::-webkit-details-marker{display:none}.gb-account-head{padding:12px 16px;border-bottom:1px solid var(--gemboss-divider)}.gb-account-name{font-size:13px;font-weight:600;color:var(--gemboss-text-strong)}.gb-account-email{font-size:12px;color:var(--gemboss-text-muted)}.gb-account-role{display:inline-block;margin-top:4px;padding:1px 6px;border-radius:4px;font-size:11px;font-weight:600;color:var(--gemboss-active-fg);background:var(--gemboss-active-bg)}.gb-account-form{margin:0}.gnav-scroll::-webkit-scrollbar{width:9px}.gnav-scroll::-webkit-scrollbar-track{background:transparent}.gnav-scroll::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:6px;border:2px solid transparent;background-clip:content-box}
|
|
1
|
+
.gemboss-popover-surface{background:var(--gemboss-surface);background:color-mix(in srgb,var(--gemboss-surface) 93%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.4);backdrop-filter:blur(14px) saturate(1.4);border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-lg);box-shadow:var(--gemboss-shadow-raised)}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.gemboss-popover-surface{background:var(--gemboss-surface)}}.icon-nav{position:fixed;top:56px;left:0;z-index:200;height:calc(100dvh - 56px);background:var(--gemboss-rail-bg);border-right:1px solid var(--gemboss-divider);display:flex;flex-direction:column;padding-top:8px;overflow:hidden}.gemboss-account-menu{position:absolute;top:calc(100% + 6px);right:0;min-width:220px;z-index:320;overflow:hidden}.gemboss-account-menu-item,.ui-menu__item{display:block;width:100%;min-height:44px;padding:12px 16px;border:0;background:transparent;font:inherit;font-size:13px;color:var(--gemboss-text);text-align:left;text-decoration:none;cursor:pointer;transition:background var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gemboss-account-menu-item:hover,.ui-menu__item:hover{background:var(--gemboss-hover)}.gemboss-account-menu-item:focus-visible,.ui-menu__item:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:-2px;background:var(--gemboss-hover)}.gemboss-account-menu-item.danger,.ui-menu__item--danger{color:var(--gemboss-danger-strong)}.gemboss-account-chip{width:30px;height:30px;border:1px solid #cfd6ce;border-radius:var(--gemboss-radius-full);background:#f5f7f4;color:#303633;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:11px;font-weight:700;cursor:pointer}.gemboss-platform-main{box-sizing:border-box;min-height:100dvh;padding-top:56px;background:var(--gemboss-app-bg)}.icon-nav{top:56px;height:calc(100dvh - 56px);background:var(--gemboss-nav-bg);border-right-color:var(--gemboss-divider)}@media (max-width: 1040px){.gemboss-platform-topbar{grid-template-columns:minmax(120px,1fr) minmax(220px,520px) minmax(120px,1fr)}}@media (max-width: 760px){.gemboss-platform-main{margin-left:0}}.gemboss-account-chip{width:32px;height:32px;border-radius:50%;background:var(--gemboss-primary);color:#fff;font-weight:600;font-size:12px;display:inline-flex;align-items:center;justify-content:center;border:none;cursor:pointer;transition:transform var(--gemboss-transition-base) ease}.gemboss-account-chip:hover{transform:scale(1.05)}.gemboss-account-chip:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gemboss-platform-main{margin-top:56px;min-height:calc(100vh - 56px);padding:24px;background:#fafafb}@media (max-width: 768px){.gemboss-platform-main{margin-left:0;padding:16px}}.gemboss-platform-shell{display:block;min-height:100vh;background:var(--gemboss-app-bg)}.gemboss-platform-topbar{position:fixed;inset:0 0 auto;z-index:300;height:56px;border-bottom:1px solid var(--gemboss-divider);background:var(--gemboss-topbar-bg);display:grid;grid-template-columns:minmax(200px,1fr) minmax(280px,560px) minmax(200px,1fr);align-items:center;gap:16px;padding:0 16px;box-shadow:var(--gemboss-shadow-resting)}:root:has(.gemboss-platform-topbar){scroll-padding-top:64px}.gemboss-account-chip{width:32px;height:32px;border:1px solid var(--gemboss-chip-line);border-radius:var(--gemboss-radius-full);background:var(--gemboss-surface);color:var(--gemboss-chip-ink);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:11px;font-weight:700;cursor:pointer;transition:border-color var(--gemboss-transition-base) ease,background-color var(--gemboss-transition-base) ease}.gemboss-account-chip:hover{border-color:var(--gemboss-chip-line-hover);background:var(--gemboss-chip-bg-hover);transform:none}.icon-nav{position:fixed;top:56px;left:0;z-index:200;height:calc(100dvh - 56px);border-right:1px solid var(--gemboss-divider);background:var(--gemboss-nav-bg);padding-top:12px}.gemboss-platform-main{min-height:calc(100vh - 56px);margin-top:56px;background:var(--gemboss-app-bg);padding:24px}@media (max-width: 1120px){.gemboss-platform-topbar{grid-template-columns:220px minmax(220px,1fr) auto;gap:12px}}@media (max-width: 760px){.gemboss-platform-topbar{height:auto;min-height:56px;grid-template-columns:minmax(0,1fr) auto;padding:12px}.gemboss-account-chip,.icon-nav{display:none}.gemboss-platform-main{margin-left:0;padding:16px}}.gnav-scroll{scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-assistant-railfoot.is-button{width:100%;border:none;background:none;cursor:pointer;text-align:left;font:inherit;border-radius:8px;transition:background .12s ease,color .12s ease}.gemboss-assistant-railfoot.is-button:hover{background:var(--gemboss-primary-soft);color:var(--gemboss-primary-dark)}.gemboss-assistant-empty{padding:24px 20px;color:var(--gemboss-text-muted);font-size:13px}@media (max-width: 760px){.gemboss-platform-topbar{display:flex;align-items:center;gap:8px;height:56px;min-height:56px;padding:0 12px}.gemboss-account-chip{display:inline-flex}.gemboss-platform-main{padding-top:16px;padding-bottom:calc(56px + env(safe-area-inset-bottom))}}@media (pointer: coarse){.gemboss-account-chip{width:44px;height:44px}.gnav-item{min-height:44px}.gemboss-assistant-collapse,.gemboss-assistant-newchat{min-height:44px;min-width:44px}}.icon-nav{width:240px;padding:12px 0 0;overflow:hidden;background:var(--gemboss-nav-bg);display:flex;flex-direction:column}.gnav-scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding-inline:12px}.gnav-bottom{padding:0 12px 12px}.gnav-item{display:flex;align-items:center;gap:12px;width:100%;padding:8px 12px;margin:1px 0;border:0;background:transparent;cursor:pointer;text-align:left;border-radius:var(--gemboss-radius-md);text-decoration:none;font-family:inherit;color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:500;line-height:1.2;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gnav-item:hover{background:var(--gemboss-nav-hover)}.gnav-item:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gnav-item.active{color:var(--gemboss-active-fg);font-weight:600}.gnav-group:not(.has-active-child)>.gnav-item.active{background:var(--gemboss-active-bg)}.gnav-group:not(.has-active-child)>.gnav-item.active:hover{background:var(--gemboss-active-bg)}.gnav-group.has-active-child>.gnav-item.active:hover{background:var(--gemboss-nav-hover)}.gnav-ico{flex:0 0 20px;width:20px;height:20px;display:grid;place-items:center}.gnav-ico svg{width:20px;height:20px;fill:currentColor}.gnav-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gnav-sub{list-style:none;margin:1px 0 6px;padding:0}.gnav-subitem{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 12px 6px 44px;margin:1px 0;border-radius:var(--gemboss-radius-sm);color:var(--gemboss-text-muted);font-size:13px;line-height:1.2;text-decoration:none;white-space:nowrap;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}@media (pointer: coarse){.gnav-subitem{min-height:44px}}.gnav-subitem:hover{background:var(--gemboss-nav-hover);color:var(--gemboss-text)}.gnav-subitem.active{color:var(--gemboss-active-fg);font-weight:600;background:var(--gemboss-active-bg)}.gnav-subitem.active:hover{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gnav-subitem.active:before{content:"";position:absolute;left:20px;top:50%;transform:translateY(-50%);width:3px;height:15px;border-radius:2px;background:var(--gemboss-primary)}.gnav-subitem.is-soon{opacity:.5;cursor:default}.gnav-subitem em{font-style:normal;font-size:var(--gemboss-fs-micro);font-weight:600;letter-spacing:.04em;text-transform:uppercase;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-sm);padding:1px 6px}.gnav-sep{height:1px;background:var(--gemboss-divider);margin:8px 6px}.gnav-item.gnav-assistant{color:var(--gemboss-accent-strong);font-weight:600;background:var(--gemboss-accent-soft)}.gnav-item.gnav-assistant .gnav-ico svg{fill:var(--gemboss-accent)}.gnav-item.gnav-assistant:hover{background:color-mix(in srgb,var(--gemboss-accent) 16%,var(--gemboss-surface))}.gnav-item.gnav-assistant.active{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gnav-item.gnav-assistant.active .gnav-ico svg{fill:var(--gemboss-active-fg)}.gemboss-platform-main{margin-left:240px}.gemboss-mobile-menu-btn,.gemboss-mobile-nav-backdrop{display:none}@media (max-width: 760px){.gemboss-platform-main{margin-left:0;padding-bottom:env(safe-area-inset-bottom)}.gemboss-mobile-menu-btn{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:38px;height:38px;margin-left:-2px;border:0;border-radius:8px;background:transparent;cursor:pointer;color:var(--gemboss-text)}.gemboss-mobile-menu-btn:active{background:var(--gemboss-hover)}.icon-nav{display:flex;width:min(82vw,300px);transform:translate(-100%);transition:transform .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:none}.gemboss-platform-shell.is-mobile-nav-open .icon-nav{transform:translate(0);box-shadow:2px 0 26px #1f1e1d33}.gemboss-mobile-nav-backdrop{display:block;position:fixed;inset:56px 0 0;width:100%;border:0;padding:0;background:#14131261;opacity:0;pointer-events:none;transition:opacity .22s ease;z-index:999}.gemboss-platform-shell.is-mobile-nav-open .gemboss-mobile-nav-backdrop{opacity:1;pointer-events:auto}}@media (max-width: 305.98px){.gemboss-platform-topbar{padding:0 8px}}@media (min-width: 306px) and (max-width: 460px){.gemboss-platform-topbar{padding:0 8px}.gemboss-mobile-menu-btn,.gemboss-account-chip{width:44px;height:44px}}.gemboss-assistant-chatslot{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0}.gemboss-assistant-chatslot[hidden]{display:none}.gemboss-assistant-page>.gemboss-assistant-tabs{flex:0 0 auto;display:flex;align-items:center;gap:4px;padding:4px 8px 0;overflow-x:auto;scrollbar-width:none}.gemboss-assistant-tabs::-webkit-scrollbar{display:none}.gemboss-assistant-tab{display:flex;align-items:center;flex:0 1 auto;min-width:0;max-width:190px;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-md);background:transparent}.gemboss-assistant-tab.active{background:var(--gemboss-active-bg);border-color:var(--gemboss-active-bg)}.gemboss-assistant-tab-main{display:flex;align-items:center;gap:6px;min-width:0;min-height:44px;padding:0 4px 0 8px;border:0;background:transparent;font:inherit;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted);cursor:pointer}.gemboss-assistant-tab.active .gemboss-assistant-tab-main{color:var(--gemboss-text-strong)}.gemboss-assistant-tab-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gemboss-assistant-tab-dot{flex:0 0 auto;width:6px;height:6px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-divider)}.gemboss-assistant-tab-dot.is-running{background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}.gemboss-assistant-tab-close{flex:0 0 auto;width:44px;height:44px;display:grid;place-items:center;border:0;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;padding:0}.gemboss-assistant-tab-close:hover{color:var(--gemboss-text-strong)}.gemboss-assistant-tab-close svg{width:14px;height:14px}.gemboss-assistant-sronly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.gemboss-assistant-thread-running{flex:0 0 auto;width:6px;height:6px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}@media (prefers-reduced-motion: reduce){.gemboss-assistant-tab-dot.is-running,.gemboss-assistant-thread-running{animation:none}}.gemboss-assistant-route-claim{display:block;height:100%}.gemboss-assistant-layout.is-dock{height:auto;min-height:0}.gemboss-assistant-layout.is-dock .gemboss-assistant-page{height:auto;max-width:none;padding:4px 0 8px}.gnav-item.gnav-assistant{position:relative}body.gemboss-assistant-busy .gnav-item.gnav-assistant:after,body.gemboss-assistant-unread .gnav-item.gnav-assistant:after{content:"";position:absolute;top:6px;left:26px;width:8px;height:8px;border-radius:50%;border:2px solid var(--gemboss-surface)}body.gemboss-assistant-busy .gnav-item.gnav-assistant:after{background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}body.gemboss-assistant-unread .gnav-item.gnav-assistant:after{background:var(--gemboss-success-strong)}@media (prefers-reduced-motion: reduce){body.gemboss-assistant-busy .gnav-item.gnav-assistant:after{animation:none}}.gemboss-assistant-layout{display:flex;height:calc(100dvh - 56px);width:100%;min-height:0}.gemboss-assistant-rail{flex:0 0 264px;width:264px;display:flex;flex-direction:column;min-height:0;border-right:1px solid var(--gemboss-divider);background:transparent;padding:16px 12px 12px;gap:12px;transition:flex-basis .18s ease,width .18s ease}.gemboss-assistant-rail-top{display:flex;align-items:center;gap:6px}.gemboss-assistant-newchat{display:flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0;padding:12px;border:1px solid var(--gemboss-divider);border-radius:12px;background:transparent;color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:600;cursor:pointer;transition:background .12s ease,border-color .12s ease}.gemboss-assistant-newchat:hover{background:#00000009;border-color:var(--gemboss-text-muted)}.gemboss-assistant-newchat svg{width:17px;height:17px;fill:currentColor;flex:0 0 auto}.gemboss-assistant-newchat span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1 1 auto}.gemboss-assistant-kbd{flex:0 0 auto;font-size:var(--gemboss-fs-micro);font-weight:600;line-height:1;padding:4px 6px;border:1px solid var(--gemboss-divider);border-radius:6px;background:transparent;color:var(--gemboss-text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gemboss-assistant-search:focus-within .gemboss-assistant-kbd{display:none}.gemboss-assistant-collapse{flex:0 0 auto;display:grid;place-items:center;width:34px;height:34px;border:0;border-radius:8px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.gemboss-assistant-collapse:hover{background:#0000000d;color:var(--gemboss-text)}.gemboss-assistant-collapse svg{width:16px;height:16px;fill:currentColor}.gemboss-assistant-search{gap:6px}.gemboss-assistant-search>svg{width:15px;height:15px;fill:var(--gemboss-text-muted);flex:0 0 auto}.gemboss-assistant-search-clear{display:grid;place-items:center;width:20px;height:20px;border:0;border-radius:6px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer}.gemboss-assistant-search-clear:hover{background:#00000012;color:var(--gemboss-text)}.gemboss-assistant-search-clear svg{width:13px;height:13px;fill:currentColor}.gemboss-assistant-railfoot{flex:0 0 auto;display:flex;align-items:center;gap:6px;padding:8px 12px 2px;border-top:1px solid var(--gemboss-divider);margin-top:4px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption);line-height:1.35}.gemboss-assistant-railfoot svg{width:13px;height:13px;flex:0 0 auto;fill:currentColor;opacity:.8}.gemboss-assistant-threads{flex:1 1 auto;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:2px}.gemboss-assistant-threads-empty{padding:16px 8px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption)}.gemboss-assistant-group{display:flex;flex-direction:column;gap:2px}.gemboss-assistant-group+.gemboss-assistant-group{margin-top:12px}.gemboss-assistant-group-label{padding:4px 12px;font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--gemboss-text-muted);text-transform:uppercase}.gemboss-assistant-thread{position:relative;display:flex;align-items:center;border-radius:8px;transition:background .12s ease}.gemboss-assistant-thread:hover{background:var(--gemboss-hover, rgba(0,0,0,.04))}.gemboss-assistant-thread.active{background:#00000012}.gemboss-assistant-thread-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 12px;border:0;background:transparent;text-align:left;cursor:pointer}.gemboss-assistant-thread-titlerow{display:flex;align-items:center;gap:6px;width:100%;min-width:0}.gemboss-assistant-pin-dot{width:12px;height:12px;flex:0 0 auto;fill:var(--gemboss-text-muted)}.gemboss-assistant-thread-title{flex:1 1 auto;min-width:0;font-size:13px;font-weight:500;color:var(--gemboss-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gemboss-assistant-thread-meta{font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-assistant-thread.menu-open{background:#00000012}.gemboss-assistant-thread.menu-open .gemboss-assistant-thread-actions{opacity:1}.gemboss-assistant-menu{z-index:60;width:184px;padding:6px;display:flex;flex-direction:column}.gemboss-assistant-menu-confirm{padding:8px 12px 6px;font-size:var(--gemboss-fs-caption);font-weight:600;color:var(--gemboss-text)}.gemboss-assistant-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;border-radius:8px;background:transparent;text-align:left;font-size:13px;color:var(--gemboss-text);cursor:pointer}.gemboss-assistant-menu button:hover{background:var(--gemboss-hover, rgba(0,0,0,.05))}.gemboss-assistant-menu button.danger{color:var(--gemboss-danger-strong)}.gemboss-assistant-menu button svg{width:15px;height:15px;fill:currentColor;flex:0 0 auto}.gemboss-assistant-thread-actions{position:absolute;right:6px;display:flex;gap:2px;opacity:0;transition:opacity .12s ease}.gemboss-assistant-thread:hover .gemboss-assistant-thread-actions,.gemboss-assistant-thread:focus-within .gemboss-assistant-thread-actions{opacity:1}.gemboss-assistant-thread-act{display:grid;place-items:center;width:26px;height:26px;border:0;border-radius:8px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.gemboss-assistant-thread-act:hover{background:#00000012;color:var(--gemboss-text)}.gemboss-assistant-thread-act.danger:hover{color:var(--gemboss-danger-strong)}.gemboss-assistant-thread-act svg{width:15px;height:15px;fill:currentColor}.gemboss-assistant-thread.editing{background:#00000012}.gemboss-assistant-thread-edit{display:flex;align-items:center;gap:2px;width:100%;padding:6px}.gemboss-assistant-thread-edit input{flex:1 1 auto;min-width:0}.gemboss-assistant-layout .gemboss-assistant-page{height:100%;max-width:820px;flex:1 1 auto;min-width:0;padding-top:16px}.gemboss-assistant-layout .gemboss-assistant-page.is-switching{opacity:.55;transition:opacity .12s ease;pointer-events:none}.gemboss-assistant-rail.is-collapsed{flex-basis:60px;width:60px;padding:16px 8px 12px}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-rail-top{flex-direction:column;gap:8px}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-newchat{justify-content:center;padding:8px;flex:0 0 auto}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-newchat span,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-search,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-railfoot,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-threads{display:none}@media (max-width: 760px){.gemboss-assistant-rail{flex-basis:60px;width:60px;padding:16px 8px 12px}.gemboss-assistant-rail .gemboss-assistant-rail-top{flex-direction:column;gap:8px}.gemboss-assistant-newchat{justify-content:center;padding:8px;flex:0 0 auto}.gemboss-assistant-newchat span,.gemboss-assistant-search,.gemboss-assistant-railfoot,.gemboss-assistant-threads,.gemboss-assistant-collapse{display:none}}.gemboss-assistant-page{height:calc(100dvh - 56px);width:100%;max-width:760px;margin:0 auto;padding:24px 0 16px;display:flex;flex-direction:column;min-height:0}.gemboss-assistant-page>*{flex:1 1 auto;min-height:0}.gemboss-assistant-empty{flex:1;display:grid;place-items:center;color:var(--gemboss-text-muted);font-size:14px}.gemboss-platform-shell{display:flow-root}.gemboss-platform-main{padding-bottom:calc(24px + var(--gemboss-invite-h, 0px))}@keyframes gemboss-assistant-pulse{0%,to{opacity:1}50%{opacity:.35}}.gb-account{position:relative}.gb-account>summary{list-style:none}.gb-account>summary::-webkit-details-marker{display:none}.gb-account-head{padding:12px 16px;border-bottom:1px solid var(--gemboss-divider)}.gb-account-name{font-size:13px;font-weight:600;color:var(--gemboss-text-strong)}.gb-account-email{font-size:12px;color:var(--gemboss-text-muted)}.gb-account-role{display:inline-block;margin-top:4px;padding:1px 6px;border-radius:4px;font-size:11px;font-weight:600;color:var(--gemboss-active-fg);background:var(--gemboss-active-bg)}.gb-account-form{margin:0}.gnav-scroll::-webkit-scrollbar{width:9px}.gnav-scroll::-webkit-scrollbar-track{background:transparent}.gnav-scroll::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:6px;border:2px solid transparent;background-clip:content-box}
|
package/src/team-chat-data.ts
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* The rules (GemCare origin/main, 20/10/2026):
|
|
8
8
|
* - A message is GROUPED under the one before it (no avatar, no name line) when the same person wrote both, on the same
|
|
9
9
|
* day, less than 5 minutes apart, and it is not a reply (a reply starts a turn of its own: it answers someone else).
|
|
10
|
-
* - A day separator comes before the first message and before the first message of each new day
|
|
11
|
-
*
|
|
10
|
+
* - A day separator comes before the first message and before the first message of each new day: the viewer's local day,
|
|
11
|
+
* or the calendar day of `timeZone` when given. A new day also breaks a group: two lines either side of midnight are
|
|
12
|
+
* two turns.
|
|
12
13
|
* - The "New messages" line comes before the first message someone ELSE wrote that the viewer has not read. The
|
|
13
14
|
* viewer's own messages after the mark are not "new". The line also breaks a group, so the first new message
|
|
14
15
|
* always shows who wrote it.
|
|
@@ -36,23 +37,55 @@ export type ChatRowOptions<M> = {
|
|
|
36
37
|
isUnread?: (message: M) => boolean;
|
|
37
38
|
/** Messages closer than this are one turn. Default 5 minutes, as GemCare. */
|
|
38
39
|
groupWithinMs?: number;
|
|
40
|
+
/**
|
|
41
|
+
* An IANA zone ("Asia/Ho_Chi_Minh"): days are that zone's calendar days instead of the process's local ones. Give it on
|
|
42
|
+
* a screen the server renders first: the server's zone (UTC on Railway) is not the member's, so a message at 00:30 in
|
|
43
|
+
* Hanoi fell on "yesterday" on the server and "today" in the browser, and the two drew different day separators (React
|
|
44
|
+
* #418, GemCommunity /chat 20/10/2026). An unknown name falls back to the local day.
|
|
45
|
+
*/
|
|
46
|
+
timeZone?: string;
|
|
39
47
|
};
|
|
40
48
|
|
|
41
49
|
const toDate = (at: string | number | Date) => (at instanceof Date ? at : new Date(at));
|
|
42
50
|
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
const ZONE_DAY = new Map<string, Intl.DateTimeFormat | null>();
|
|
52
|
+
/** [year, month 1–12, day] of `d` in `timeZone`, or in local time when there is no zone, it is unknown, or `d` is invalid. */
|
|
53
|
+
function dayParts(at: string | number | Date, timeZone?: string): [number, number, number] {
|
|
45
54
|
const d = toDate(at);
|
|
46
|
-
|
|
55
|
+
if (timeZone) {
|
|
56
|
+
let f = ZONE_DAY.get(timeZone);
|
|
57
|
+
if (f === undefined) {
|
|
58
|
+
try { f = new Intl.DateTimeFormat("en-US", { timeZone, year: "numeric", month: "numeric", day: "numeric" }); } catch { f = null; }
|
|
59
|
+
ZONE_DAY.set(timeZone, f);
|
|
60
|
+
}
|
|
61
|
+
if (f && !Number.isNaN(d.getTime())) {
|
|
62
|
+
const p: Record<string, number> = {};
|
|
63
|
+
for (const x of f.formatToParts(d)) if (x.type !== "literal") p[x.type] = Number(x.value);
|
|
64
|
+
return [p.year, p.month, p.day];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return [d.getFullYear(), d.getMonth() + 1, d.getDate()];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The calendar day (local, or of `timeZone`), as a key: two dates with the same key are the same day. */
|
|
71
|
+
export function chatDayKey(at: string | number | Date, timeZone?: string): string {
|
|
72
|
+
const [y, m, d] = dayParts(at, timeZone);
|
|
73
|
+
return `${y}-${m}-${d}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The same day as ISO 8601 ("2026-10-21"), for a day separator's `<time dateTime>`. */
|
|
77
|
+
export function chatDayISO(at: string | number | Date, timeZone?: string): string {
|
|
78
|
+
const [y, m, d] = dayParts(at, timeZone);
|
|
79
|
+
return `${y}-${String(m).padStart(2, "0")}-${String(d).padStart(2, "0")}`;
|
|
47
80
|
}
|
|
48
81
|
|
|
49
82
|
/** "Today", "Yesterday", or null (the caller formats older days with its own locale, e.g. "Mon, Sep 28"). */
|
|
50
|
-
export function chatDayWord(at: string | number | Date, now: Date = new Date()): "Today" | "Yesterday" | null {
|
|
51
|
-
const key = chatDayKey(at);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return key ===
|
|
83
|
+
export function chatDayWord(at: string | number | Date, now: Date = new Date(), timeZone?: string): "Today" | "Yesterday" | null {
|
|
84
|
+
const key = chatDayKey(at, timeZone);
|
|
85
|
+
const [y, m, d] = dayParts(now, timeZone);
|
|
86
|
+
if (key === `${y}-${m}-${d}`) return "Today";
|
|
87
|
+
const p = new Date(Date.UTC(y, m - 1, d - 1)); // calendar arithmetic: the day before, whatever the zone
|
|
88
|
+
return key === `${p.getUTCFullYear()}-${p.getUTCMonth() + 1}-${p.getUTCDate()}` ? "Yesterday" : null;
|
|
56
89
|
}
|
|
57
90
|
|
|
58
91
|
/** The rows to draw, in order: day separators, the "New messages" line, and each message with its `grouped` flag. */
|
|
@@ -65,8 +98,8 @@ export function teamChatRows<M extends ChatRowMessage>(messages: readonly M[], o
|
|
|
65
98
|
messages.forEach((m, i) => {
|
|
66
99
|
const prev = i > 0 ? messages[i - 1] : undefined;
|
|
67
100
|
const at = toDate(m.at);
|
|
68
|
-
const newDay = !prev || chatDayKey(prev.at) !== chatDayKey(at);
|
|
69
|
-
if (newDay) rows.push({ kind: "day", key: chatDayKey(at), date: at });
|
|
101
|
+
const newDay = !prev || chatDayKey(prev.at, opts.timeZone) !== chatDayKey(at, opts.timeZone);
|
|
102
|
+
if (newDay) rows.push({ kind: "day", key: chatDayKey(at, opts.timeZone), date: at });
|
|
70
103
|
const isFirstNew = i === firstNew;
|
|
71
104
|
if (isFirstNew) rows.push({ kind: "new" });
|
|
72
105
|
const grouped = Boolean(
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(v){"use strict";var j=v.gembossUI||(v.gembossUI={});if(j.teamChat)return;var H={reaction:'<path d="M16.5 10a6.5 6.5 0 1 1-6.5-6.5"/><path d="M7.5 11.8s.9 1.2 2.5 1.2 2.5-1.2 2.5-1.2"/><path d="M7.8 8.2h.01M12.2 8.2h.01"/><path d="M15 2.5v4M13 4.5h4"/>',reply:'<path d="M8 13.5 3.5 9 8 4.5M3.5 9h8a5 5 0 0 1 5 5v2"/>',thread:'<path d="M3 4.5h14v9H8.5L5 16.5v-3H3z"/><path d="M6.5 8h7M6.5 10.5h4.5"/>',chevronsDown:'<path d="M6 5.5l4 4 4-4M6 10.5l4 4 4-4"/>',hash:'<path d="M8 3.5 6.5 16.5M13.5 3.5 12 16.5M4 7.5h12.5M3.5 12.5H16"/>',lock:'<rect x="4.5" y="9" width="11" height="8" rx="1.5"/><path d="M7 9V6.5a3 3 0 0 1 6 0V9"/>',user:'<circle cx="10" cy="7" r="3.2"/><path d="M3.8 16.5c.8-2.8 3.3-4.5 6.2-4.5s5.4 1.7 6.2 4.5"/>',more:'<circle cx="4.5" cy="10" r="1"/><circle cx="10" cy="10" r="1"/><circle cx="15.5" cy="10" r="1"/>'},W=["\u{1F44D}","\u2705"],Y=["\u{1F44D}","\u2705","\u{1F64F}","\u{1F389}","\u{1F602}","\u2764\uFE0F","\u{1F440}","\u{1F64C}","\u{1F525}"],D=[["Smileys",[["\u{1F600}","grin smile happy"],["\u{1F603}","smile happy"],["\u{1F604}","smile laugh happy"],["\u{1F601}","grin beam"],["\u{1F606}","laugh squint"],["\u{1F605}","sweat smile relief"],["\u{1F602}","joy tears laugh lol"],["\u{1F923}","rofl rolling laugh"],["\u{1F60A}","blush smile"],["\u{1F607}","innocent halo"],["\u{1F642}","slight smile ok"],["\u{1F609}","wink"],["\u{1F60D}","heart eyes love"],["\u{1F970}","love hearts"],["\u{1F618}","kiss"],["\u{1F60B}","yum tasty"],["\u{1F61C}","wink tongue"],["\u{1F92A}","zany crazy"],["\u{1F917}","hug"],["\u{1F92D}","oops giggle"],["\u{1F914}","think hmm"],["\u{1F928}","raised eyebrow doubt"],["\u{1F610}","neutral"],["\u{1F636}","no words"],["\u{1F644}","eye roll"],["\u{1F60F}","smirk"],["\u{1F62C}","grimace awkward"],["\u{1F60C}","relieved"],["\u{1F634}","sleep tired"],["\u{1F637}","mask sick"],["\u{1F92F}","mind blown"],["\u{1F973}","party celebrate"],["\u{1F60E}","cool sunglasses"],["\u{1F913}","nerd"],["\u{1F615}","confused"],["\u{1F61F}","worried"],["\u{1F62E}","wow surprised"],["\u{1F632}","astonished"],["\u{1F633}","flushed embarrassed"],["\u{1F97A}","pleading please"],["\u{1F622}","cry sad"],["\u{1F62D}","sob crying"],["\u{1F631}","scream shock"],["\u{1F624}","huff frustrated"],["\u{1F621}","angry mad"],["\u{1F92C}","swear"],["\u{1F480}","dead skull"],["\u{1FAE0}","melting"],["\u{1FAE1}","salute"]]],["Hands",[["\u{1F44D}","like thumbs up yes ok"],["\u{1F44E}","dislike thumbs down no"],["\u{1F44C}","ok perfect"],["\u270C\uFE0F","peace victory"],["\u{1F91E}","fingers crossed luck"],["\u{1F91F}","love you"],["\u{1F918}","rock"],["\u{1F44F}","clap applause"],["\u{1F64C}","raise hands hooray"],["\u{1F450}","open hands"],["\u{1F91D}","handshake deal"],["\u{1F64F}","thanks please pray"],["\u{1F4AA}","strong muscle"],["\u{1F440}","eyes looking"],["\u{1FAF6}","heart hands"],["\u270D\uFE0F","writing"],["\u{1F44B}","wave hi bye"],["\u261D\uFE0F","point up"],["\u{1F447}","point down"],["\u{1F449}","point right"],["\u{1F448}","point left"],["\u{1F919}","call me"],["\u{1F590}\uFE0F","stop hand"],["\u{1F90C}","pinched"]]],["Marks",[["\u2764\uFE0F","heart love red"],["\u{1F9E1}","orange heart"],["\u{1F49B}","yellow heart"],["\u{1F49A}","green heart"],["\u{1F499}","blue heart"],["\u{1F49C}","purple heart"],["\u{1F5A4}","black heart"],["\u{1F4AF}","hundred perfect"],["\u2705","done check yes"],["\u2611\uFE0F","checked box"],["\u2714\uFE0F","check mark"],["\u274C","no cross wrong"],["\u2757","important exclamation"],["\u2753","question"],["\u26A0\uFE0F","warning"],["\u{1F525}","fire hot lit"],["\u2B50","star"],["\u2728","sparkles new"],["\u{1F4A1}","idea"],["\u{1F4CC}","pin"],["\u{1F680}","rocket ship launch"],["\u{1F3AF}","target goal"],["\u{1F197}","ok button"],["\u{1F195}","new"],["\u{1F534}","red circle urgent"],["\u{1F7E2}","green circle"],["\u{1F7E1}","yellow circle"],["\u2795","plus one add"]]],["Work",[["\u{1F389}","party tada celebrate"],["\u{1F38A}","confetti"],["\u{1F3C6}","trophy win"],["\u{1F947}","gold medal first"],["\u{1F381}","gift"],["\u2615","coffee"],["\u{1F37B}","cheers beer"],["\u{1F355}","pizza"],["\u{1F4C8}","chart up growth"],["\u{1F4C9}","chart down"],["\u{1F4B0}","money"],["\u{1F6D2}","cart shop"],["\u{1F4E6}","package order shipping"],["\u{1F9FE}","receipt invoice"],["\u{1F4DD}","note memo"],["\u{1F4C5}","calendar date"],["\u23F0","alarm time"],["\u23F3","waiting hourglass"],["\u{1F527}","fix wrench"],["\u{1F41B}","bug"],["\u{1F9EA}","test"],["\u{1F50D}","search look"],["\u{1F4AC}","comment chat"],["\u{1F4DE}","call phone"],["\u{1F4E7}","email"],["\u{1F512}","lock private"],["\u{1F517}","link"],["\u{1F5BC}\uFE0F","image picture"],["\u{1F4BB}","laptop computer"],["\u{1F4F1}","phone mobile"],["\u{1F648}","see no evil oops"],["\u{1F649}","hear no evil"],["\u{1F916}","robot bot ai"],["\u{1F9E0}","brain"],["\u{1F451}","crown vip"],["\u{1F48E}","gem diamond"]]]],R={channels:"Channels",conversation:"Conversation",back:"Back to channels",members:"Members",hideMembers:"Hide members",showMembers:"Show members",thread:"Thread",closeThread:"Close thread",replies:function(e){return e===1?"1 reply":e+" replies"},newMessages:"New messages",edited:"(edited)",someone:"Someone who has left",actionsFor:function(e){return"Actions for the message from "+e},react:function(e,t,n){return(n?"Remove":"Add")+" "+e+" on the message from "+t},moreReactions:function(e){return"More reactions for the message from "+e},reply:"Reply",replyTo:function(e){return"Reply to the message from "+e},replyInThread:"Reply in thread",replyInThreadTo:function(e){return"Reply in thread to the message from "+e},openThread:function(e,t){return"Open the thread, "+(e===1?"1 reply":e+" replies")+(t?", "+t:"")},jump:"Jump to the latest message",jumpNew:function(e){return"Jump to the latest message, "+e+" new"},message:"Message",send:"Send",attach:"Attach a file",stopReplying:"Stop replying",privateChannel:"private channel",directMessage:"direct message",mentioningYou:function(e){return e+" mentioning you"},unread:function(e){return e+" unread"},online:"Online",away:"Away",offline:"Offline"},E=Object.prototype.hasOwnProperty;function S(e){if(!e)return R;var t={},n;for(n in R)t[n]=R[n];for(n in e)E.call(e,n)&&(t[n]=e[n]);return t}var L=function(e){return typeof Node<"u"&&e instanceof Node},C=function(){return[].filter.call(arguments,Boolean).join(" ")};function i(e,t,n){var a=document.createElement(e),r;for(r in t)t[r]!==void 0&&t[r]!==null&&t[r]!==!1&&a.setAttribute(r,String(t[r]));return A(a,n)}function A(e,t){if(t==null||typeof t=="boolean"||t==="")return e;if(Array.isArray(t)){for(var n=0;n<t.length;n++)A(e,t[n]);return e}return e.appendChild(L(t)?t:document.createTextNode(String(t))),e}var ue=function(e){return e==null?void 0:String(e)},m=function(e,t){return t&&e.addEventListener("click",t),e},G=0;function _(e,t){var n=Number(t)||20,a=document.createElement("template");return a.innerHTML='<svg viewBox="0 0 20 20" width="'+n+'" height="'+n+'" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">'+(E.call(H,e)?H[e]:"")+"</g></svg>",a.content.firstChild}function x(e,t){var n=document.createElementNS("http://www.w3.org/2000/svg",e);for(var a in t)n.setAttribute(a,t[a]);return n}var de=function(){try{return new RegExp("^\\p{L}","u")}catch{return/^[A-Za-zÀ-ɏͰ-ϿЀ-ӿ]/}}();function z(e){var t=String(e).trim().split(/\s+/).filter(Boolean),n=t.filter(function(r){return de.test(r)}),a=n.length?n:t;return a.length?(a.length===1?a[0].slice(0,2):a[0][0]+a[a.length-1][0]).toUpperCase():"?"}function V(e){var t=0,n=String(e),a,r,l;for(a=0;a<n.length;a++)r=n.charCodeAt(a),r>=55296&&r<=56319&&a+1<n.length&&(l=n.charCodeAt(a+1),l>=56320&&l<=57343&&(r=(r-55296)*1024+(l-56320)+65536,a++)),t=t*31+r>>>0;return t%8}var pe={24:"gb-avatar--24",32:"gb-avatar--32",40:"gb-avatar--40",56:"gb-avatar--56"};function I(e,t,n,a){return n=n===void 0?24:n,i("span",{class:C("gb-avatar",pe[n],a),"data-tone":V(e),"aria-hidden":"true"},t?i("img",{class:"gb-avatar-img",src:t,alt:"",loading:"lazy",width:n,height:n}):z(e))}var T={},P=[];D.forEach(function(e){e[1].forEach(function(t){T[t[0]]=t[1],P.push(t[0])})});var Q=function(e){return typeof e=="string"&&E.call(T,e)},O=function(e){return E.call(T,e)?T[e]:""};function X(e){var t=String(e).trim().toLowerCase();return t?P.filter(function(n){return T[n].indexOf(t)>-1}):P.slice()}function Z(e){return e.length>2?e.slice(0,2).join(", ")+" +"+(e.length-2):e.join(", ")}var $="gemboss-ui:reactions-recent",U=9;function ee(e){var t=[];return e.concat(Y).forEach(function(n){Q(n)&&t.indexOf(n)<0&&t.length<U&&t.push(n)}),t}function te(){try{var e=JSON.parse(v.localStorage&&v.localStorage.getItem($)||"[]");return Array.isArray(e)?e.filter(function(t){return typeof t=="string"&&O(t)!==""}).slice(0,U):[]}catch{return[]}}function fe(e){try{var t=[e].concat(te().filter(function(n){return n!==e})).slice(0,U);v.localStorage&&v.localStorage.setItem($,JSON.stringify(t))}catch{}}var q=function(e,t){return e.some(function(n){return n.emoji===t&&n.mine})};function B(e){var t=e.items||[],n=ee(te()),a=function(c){var d=q(t,c);return m(i("button",{type:"button",class:"ui-reaction-picker__btn",title:O(c).split(" ")[0]||c,"aria-label":((d?"Remove":"Add")+" "+c+" "+O(c)).trim(),"aria-pressed":String(d)},c),function(){e.onPick(c)})},r=function(c){return i("div",{class:"ui-reaction-picker__grid"},c.map(a))},l=function(c){return i("p",{class:"ui-reaction-picker__head"},c)},u=i("input",{type:"search",class:"gemboss-field ui-reaction-picker__search",placeholder:"Search emoji","aria-label":"Search emoji",autocomplete:"off",value:""}),o=i("div",{class:"ui-reaction-picker__body"}),g=function(){var c=u.value,d=c.trim()?X(c):null,s=[];d?s.push(d.length?r(d):i("p",{class:"ui-reaction-picker__empty"},"No emoji matches.")):(s.push(l("Frequently used"),r(n)),D.forEach(function(b){s.push(l(b[0]),r(b[1].map(function(y){return y[0]})))})),o.replaceChildren.apply(o,s)},h=i("div",{id:e.id,class:"ui-reaction-picker",role:"group","aria-label":"Pick a reaction"},[u,o]);return u.addEventListener("input",g),h.addEventListener("keydown",function(c){if(c.key==="Escape"){c.preventDefault(),c.stopPropagation(),e.onClose();return}var d=[].slice.call(o.querySelectorAll(".ui-reaction-picker__btn"));if(c.target===u){c.key==="Enter"&&(c.preventDefault(),d[0]&&d[0].click()),c.key==="ArrowDown"&&(c.preventDefault(),d[0]&&d[0].focus());return}var s=d.indexOf(document.activeElement);if(!(s<0)){var b=o.querySelector(".ui-reaction-picker__grid"),y=Math.max(1,Math.round((b?b.getBoundingClientRect().width:44)/44)),p={ArrowRight:1,ArrowLeft:-1,ArrowDown:y,ArrowUp:-y}[c.key];if(p){if(c.preventDefault(),s+p<0){u.focus();return}d[Math.min(d.length-1,s+p)]&&d[Math.min(d.length-1,s+p)].focus()}}}),g(),h}function ne(e){var t=e.items||[],n=e.target===void 0?"this":e.target,a=e.canReact===void 0?!0:e.canReact;if(!t.length&&!a)return null;var r=!1,l=null,u="gb-tc-rp"+ ++G,o=null,g=function(s){if(!a){e.onSignIn&&e.onSignIn();return}q(t,s)||fe(s),e.onToggle&&e.onToggle(s)},h=i("div",{class:"ui-reactions__row"},t.map(function(s){return m(i("button",{type:"button",class:"ui-reaction"+(s.mine?" is-mine":""),"aria-pressed":ue(s.mine),title:s.names.join(", "),"aria-label":s.emoji+", "+s.names.join(", ")+". "+(s.mine?"Remove yours":"Add yours")},[i("span",{class:"ui-reaction__emoji"},s.emoji),i("span",{class:"ui-reaction__names"},Z(s.names))]),function(){g(s.emoji)})})),c=i("div",{class:C("ui-reactions",e.className)},h),d=function(s,b){r=s,o.setAttribute("aria-expanded",String(r)),r?(o.setAttribute("aria-controls",u),l=B({id:u,items:t,onPick:function(y){d(!1,!0),g(y),o.focus()},onClose:function(){d(!1,!0),o.focus()}}),c.appendChild(l),b&&l.firstChild.focus()):(o.removeAttribute("aria-controls"),l&&l.remove(),l=null),b&&e.onOpenChange&&e.onOpenChange(r)};return a&&(o=i("button",{type:"button",class:"ui-reaction-add",title:"Add reaction","aria-label":"Add a reaction to "+n,"aria-expanded":"false"},_("reaction",18)),h.appendChild(m(o,function(){d(!r,!0)})),e.open&&d(!0,!1)),c}function he(e){var t=e.read,n=e.of;if(n<=0)return null;var a=t>=n,r=Math.min(t,n)/n*Math.PI*2,l=x("svg",{viewBox:"0 0 14 14",width:"14",height:"14","aria-hidden":"true",focusable:"false"});return l.appendChild(x("circle",{cx:"7",cy:"7",r:"6",fill:a?"currentColor":"none",stroke:"currentColor","stroke-width":"1.4"})),a?l.appendChild(x("path",{class:"gb-tc-receipt__tick",d:"M4.2 7.2l1.9 1.9 3.7-4",fill:"none","stroke-width":"1.6","stroke-linecap":"round","stroke-linejoin":"round"})):t>0&&l.appendChild(x("path",{d:"M7 7 L7 1 A6 6 0 "+(r>Math.PI?1:0)+" 1 "+(7+6*Math.sin(r)).toFixed(2)+" "+(7-6*Math.cos(r)).toFixed(2)+" Z",fill:"currentColor"})),i("span",{class:C("gb-tc-receipt",a&&"gb-tc-receipt--all"),role:"img","aria-label":e.label,title:e.label},l)}function ge(e){var t={ArrowRight:1,ArrowLeft:-1}[e.key],n=[].slice.call(e.currentTarget.querySelectorAll("button:not([disabled]), summary, a[href]")).filter(function(l){return l.offsetParent!==null}),a=n.indexOf(document.activeElement);if(!(a<0)){var r=t?n[(a+t+n.length)%n.length]:e.key==="Home"?n[0]:e.key==="End"?n[n.length-1]:null;r&&(e.preventDefault(),r.focus())}}function me(e){var t=S(e.labels),n=e.author||t.someone,a=e.reactions||[],r=e.editor!=null,l=!!(e.picking&&e.onReact),u=null,o=null,g=!1,h=function(){var f=e.time;return L(f)&&g?f.cloneNode(!0):(g=!0,f)},c=function(){return C("gb-tc-msg",e.grouped&&"gb-tc-msg--grouped",e.mentionsMe&&"gb-tc-msg--mention",e.highlight&&"gb-tc-msg--highlight",e.sending&&"gb-tc-msg--sending",e.failed&&"gb-tc-msg--failed",l&&"gb-tc-msg--active",r&&"gb-tc-msg--editing",e.className)},d=i("li",{id:e.id,class:c(),"data-msg-id":e.messageId,tabindex:"-1"},e.grouped?i("time",{class:"gb-tc-msg__hover-time",datetime:e.dateTime},h()):e.avatar!=null?e.avatar:I(n,e.avatarSrc,32,"gb-tc-msg__av")),s=i("div",{class:"gb-tc-msg__main"});e.replyTo&&s.appendChild(m(i("button",{type:"button",class:"gb-tc-quote","aria-busy":e.replyTo.busy||void 0},[i("span",{class:"gb-tc-quote__who"},e.replyTo.author||t.someone),i("span",{class:"gb-tc-quote__text"},e.replyTo.excerpt)]),e.replyTo.onOpen)),s.appendChild(e.grouped?i("span",{class:"gb-tc-sr"},[n,", ",h(),": "]):i("div",{class:"gb-tc-msg__who"},[i("span",{class:"gb-tc-msg__name"},n),e.badges,i("time",{class:"gb-tc-msg__time",datetime:e.dateTime},h())])),r?s.appendChild(i("div",{class:"gb-tc-msg__editor"},e.editor)):(e.body!=null||e.edited||e.receipt)&&s.appendChild(i("div",{class:"gb-tc-msg__body"},[e.body,e.edited?i("span",{class:"gb-tc-msg__edited"},t.edited):null,e.receipt])),e.status&&s.appendChild(i("p",{class:"gb-tc-msg__status",role:e.failed?"alert":void 0},e.status)),e.attachments&&s.appendChild(i("div",{class:"gb-tc-msg__files"},e.attachments)),e.extra&&s.appendChild(i("div",{class:"gb-tc-msg__extra"},e.extra));var b=function(f,w){e.onPickingChange&&e.onPickingChange(f,w)},y=a.length?ne({items:a,onToggle:e.onReact,canReact:!!e.onReact,target:"the message from "+n,open:e.reactionsPicking,onOpenChange:function(f){b("reactions",f)}}):null,p=e.thread,K=null;p&&p.count>0&&(K=m(i("button",{type:"button",class:"gb-tc-threadprev","aria-label":t.openThread(p.count,p.last==null?"":p.last)},[p.repliers&&p.repliers.length?i("span",{class:"gb-tc-threadprev__faces","aria-hidden":"true"},p.repliers.slice(0,3).map(function(f){return I(f.name,f.src,24)})):null,i("span",{class:"gb-tc-threadprev__count"},t.replies(p.count)),p.last?i("span",{class:"gb-tc-threadprev__last"},p.last):null]),p.onOpen)),A(s,[y,K]),d.appendChild(s);var N=function(f,w){l=f,d.className=c(),o&&o.setAttribute("aria-expanded",String(l)),l?(u=B({items:a,onPick:function(Me){N(!1,!0),e.onReact(Me),o.focus()},onClose:function(){N(!1,!0),o.focus()}}),s.insertBefore(u,y||K),w&&u.firstChild.focus()):u&&(u.remove(),u=null),w&&b("bar",l)};if(!r&&!e.sending&&(e.onReact||e.onReply||e.onOpenThread||e.moreActions)){var k=i("div",{class:"gb-tc-acts",role:"toolbar","aria-label":t.actionsFor(n)});e.onReact&&(W.forEach(function(f){var w=q(a,f);k.appendChild(m(i("button",{type:"button",class:"gb-tc-act gb-tc-act--quick","aria-pressed":String(w),"aria-label":t.react(f,n,w)},f),function(){e.onReact(f)}))}),o=i("button",{type:"button",class:"gb-tc-act","aria-expanded":String(l),"aria-label":t.moreReactions(n),title:"Add reaction"},_("reaction",18)),k.appendChild(m(o,function(){N(!l,!0)}))),e.onReply&&k.appendChild(m(i("button",{type:"button",class:"gb-tc-act","aria-label":t.replyTo(n),title:t.reply},_("reply",18)),e.onReply)),e.onOpenThread&&k.appendChild(m(i("button",{type:"button",class:"gb-tc-act","aria-label":t.replyInThreadTo(n),title:t.replyInThread},_("thread",18)),e.onOpenThread)),A(k,e.moreActions),k.addEventListener("keydown",ge),d.appendChild(k)}return l&&N(!0,!1),d}function be(e,t){return i("li",{class:"gb-tc-day"},t?i("time",{class:"gb-tc-day__label",datetime:t},e):i("span",{class:"gb-tc-day__label"},e))}function ve(e){var t=S(e);return i("li",{class:"gb-tc-new"},i("span",{class:"gb-tc-new__label",role:"separator","aria-label":t.newMessages},t.newMessages))}function ye(e){return e=e||{},ae(m(i("button",{type:"button",class:"gb-tc-jump"},_("chevronsDown",20)),e.onJump),e)}function ae(e,t){t=t||{};var n=S(t.labels),a=t.count===void 0?0:t.count,r=e.querySelector(".gb-tc-jump__n");return t.visible===void 0||t.visible?e.removeAttribute("hidden"):e.setAttribute("hidden",""),e.setAttribute("aria-label",a?n.jumpNew(a):n.jump),a?(r||(r=e.appendChild(i("span",{class:"gb-tc-jump__n","aria-hidden":"true"}))),r.textContent=a>99?"99+":String(a),e):(r&&r.remove(),e)}var _e={channel:"hash",private:"lock",dm:"user"},re={online:"gb-tc-presence gb-tc-presence--online",away:"gb-tc-presence gb-tc-presence--away",offline:"gb-tc-presence gb-tc-presence--offline"};function ie(e){var t=S(e.labels),n=e.kind===void 0?"channel":e.kind,a=e.unread===void 0?0:e.unread,r=e.mentions===void 0?0:e.mentions,l=[e.name,n==="private"?t.privateChannel:n==="dm"?t.directMessage:null,r?t.mentioningYou(r):null,a?t.unread(a):null].filter(Boolean).join(", "),u=[i("span",{class:"gb-tc-channel__glyph","aria-hidden":"true"},[_(_e[n],16),n==="dm"&&e.online!==void 0?i("span",{class:re[e.online?"online":"offline"]}):null]),i("span",{class:"gb-tc-channel__name"},e.name),r?i("span",{class:"gb-tc-badge gb-tc-badge--mention","aria-hidden":"true"},"@"+r):null,a?i("span",{class:"gb-tc-badge","aria-hidden":"true"},a):null],o=C("gb-tc-channel",a>0&&"gb-tc-channel--unread");return i("li",null,m(e.href!==void 0?i("a",{class:o,href:e.href,"aria-current":e.active?"page":void 0,"aria-label":l},u):i("button",{type:"button",class:o,"aria-current":e.active?"true":void 0,"aria-label":l},u),e.onOpen))}function le(e,t,n,a){var r=(e.id==null?"gb-tc-s"+ ++G:e.id)+"-h";return i("div",{class:t[0],role:"group","aria-labelledby":r},[i("h3",{class:t[1],id:r},n),i("ul",{class:t[2]},(e.items||[]).map(function(l){return l&&!L(l)?a(l):l}))])}function ke(e){return le(e,["gb-tc-rail__section","gb-tc-rail__heading","gb-tc-rail__list"],e.label,ie)}function we(e){return le(e,["gb-tc-people__section","gb-tc-people__heading","gb-tc-people__list"],[e.label,e.count!==void 0?" \u2014 "+e.count:null],ce)}function ce(e){var t=S(e.labels),n=[i("span",{class:"gb-tc-person__av"},[e.avatar!=null?e.avatar:I(e.name,e.src,32),e.presence?i("span",{class:re[e.presence]},i("span",{class:"gb-tc-sr"},t[e.presence])):null]),i("span",{class:"gb-tc-person__text"},[i("span",{class:"gb-tc-person__name"},e.name),e.subtitle?i("span",{class:"gb-tc-person__sub"},e.subtitle):null]),e.role?i("span",{class:"gb-tc-person__role"},e.role):null],a=C("gb-tc-person",e.presence==="offline"&&"gb-tc-person--offline");return i("li",null,m(e.href!==void 0?i("a",{class:a,href:e.href,title:e.name},n):e.onSelect?i("button",{type:"button",class:a,title:e.name},n):i("div",{class:a,title:e.name},n),e.onSelect))}var F=function(e){return e instanceof Date?e:new Date(e)},se={};function J(e,t){var n=F(e),a,r,l,u;if(t){if(a=se[t],a===void 0){try{a=new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"numeric",day:"numeric"})}catch{a=null}se[t]=a}if(a&&!isNaN(n.getTime())){for(r={},l=a.formatToParts(n),u=0;u<l.length;u++)l[u].type!=="literal"&&(r[l[u].type]=Number(l[u].value));return[r.year,r.month,r.day]}}return[n.getFullYear(),n.getMonth()+1,n.getDate()]}function M(e,t){var n=J(e,t);return n[0]+"-"+n[1]+"-"+n[2]}function Ce(e,t){var n=J(e,t),a=function(r){return(r<10?"0":"")+r};return n[0]+"-"+a(n[1])+"-"+a(n[2])}function Se(e,t,n){t=t===void 0?new Date:t;var a=M(e,n),r=J(t,n),l;return a===r[0]+"-"+r[1]+"-"+r[2]?"Today":(l=new Date(Date.UTC(r[0],r[1]-1,r[2]-1)),a===l.getUTCFullYear()+"-"+(l.getUTCMonth()+1)+"-"+l.getUTCDate()?"Yesterday":null)}function Te(e,t){t=t||{};var n=t.groupWithinMs==null?5*60*1e3:t.groupWithinMs,a=-1,r=[],l,u=t.timeZone;if(t.isUnread){for(l=0;l<e.length;l++)if(t.isUnread(e[l])&&(t.meId==null||e[l].authorId!==t.meId)){a=l;break}}return e.forEach(function(o,g){var h=g>0?e[g-1]:void 0,c=F(o.at),d=!h||M(h.at,u)!==M(c,u);d&&r.push({kind:"day",key:M(c,u),date:c}),g===a&&r.push({kind:"new"}),r.push({kind:"message",message:o,grouped:!!(h&&!d&&g!==a&&o.authorId!=null&&h.authorId===o.authorId&&o.replyToId==null&&c.getTime()-F(h.at).getTime()<n)})}),r}j.teamChat={message:me,readReceipt:he,daySeparator:be,newMessagesLine:ve,jumpToLatest:ye,updateJump:ae,channelSection:ke,channelItem:ie,peopleSection:we,personRow:ce,reactions:ne,reactionPicker:B,avatar:function(e){return I(e.name,e.src,e.size,e.className)},icon:_,rows:Te,dayKey:M,dayISO:Ce,dayWord:Se,LABELS:R,initialsOf:z,avatarTone:V,isReactionEmoji:Q,reactionWords:O,searchReactions:X,reactionLabel:Z,frequentReactions:ee,QUICK_REACTIONS:W,SUGGESTED_REACTIONS:Y,REACTION_GROUPS:D};function oe(){!j.openModal&&v.console&&document.querySelector('script[src*="kit-plain"]')&&v.console.error("@gemboss/ui team-chat-plain.js: load it after kit-plain.js (kit-plain.js defines nothing when gembossUI exists)")}v.document&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",oe,{once:!0}):oe())})(typeof globalThis<"u"?globalThis:this);
|