@baack-software/baack-ts-editor 0.1.4 → 0.1.6
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/README.md +1 -1
- package/dist/chunks/chunk-5RFN34CS.js +2 -0
- package/dist/chunks/chunk-5RFN34CS.js.map +7 -0
- package/dist/chunks/{chunk-V4BSLQ2M.js → chunk-MSWF55NC.js} +53 -24
- package/dist/chunks/chunk-MSWF55NC.js.map +7 -0
- package/dist/chunks/chunk-VNUXOULZ.js +3 -0
- package/dist/chunks/chunk-VNUXOULZ.js.map +7 -0
- package/dist/chunks/dist-CF3GEGCB.js +2 -0
- package/dist/chunks/dist-CF3GEGCB.js.map +7 -0
- package/dist/editor.js +11 -10
- package/dist/editor.js.map +4 -4
- package/dist/loader.js +1 -1
- package/dist/loader.js.map +3 -3
- package/package.json +4 -3
- package/dist/chunks/chunk-V4BSLQ2M.js.map +0 -7
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ Then:
|
|
|
62
62
|
or let the editor find it by the page's path.
|
|
63
63
|
|
|
64
64
|
The API must allow your site's origin, with credentials, and editors log in
|
|
65
|
-
|
|
65
|
+
on Baack's login page, which the editor opens in a window of its own. `docs/site-integration.md` has the settings,
|
|
66
66
|
which content serves a page, what happens after a publish, the DOM events, and
|
|
67
67
|
content rendered by your own framework (islands).
|
|
68
68
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var v=Object.freeze({ACCOUNTS:"/n/v1/accounts",ACCOUNT_SETUP:"/form/account-setup",ADD_USER:"/form/add-user",ADDRESS:"/n/v1/address/",API_CLIENT:"/n/v1/apiclient/",BEARER_TOKEN:"/n/v1/bearertoken/",BOOLEAN:"/n/v1/booleanitem/",BOOLEAN_HISTORY:"/n/v1/booleanitemhistory/",CLIENT_CONTEXT:"/n/v1/clientcontext",CLIENT_IDENTIFIER:"/n/v1/clientidentifier/",COMPANIES:"/n/v1/companies",COMPANY:"/n/v1/company/",DATE_TIME:"/n/v1/datetimeitem/",DATE_TIME_HISTORY:"/n/v1/datetimeitemhistory/",DEAL:"/n/v1/deal/",DOUBLE:"/n/v1/doubleitem/",DOUBLE_HISTORY:"/n/v1/doubleitemhistory/",EMAIL:"/n/v1/email/",ENTITY:"/n/v1/entity/",ENTITY_LIST:"/n/v1/entitylist/",ENTITY_VIEW:"/v/v1/entityview/",GROUP:"/n/v1/group/",GROUP_MEMBERSHIP:"/n/v1/groupmembership/",IDENTITY:"/n/v1/identity/",IDENTITY_NOTIFICATION_INBOX:"/n/v1/identitynotificationinbox/",IMAGE:"/n/v1/imageitem/",IMAGE_HISTORY:"/n/v1/imageitemhistory/",IMAGE_FILE:"/n/v1/imageitemfile",INVOICE_LINE:"/n/v1/invoiceline/",INVOICE_REMITTANCE:"/n/v1/invoiceremittance/",JSON:"/n/v1/jsonitem/",JSON_HISTORY:"/n/v1/jsonitemhistory/",LAT_LONG:"/n/v1/latlongitem/",LAT_LONG_HISTORY:"/n/v1/latlongitemhistory/",LEAD:"/n/v1/lead/",LINK:"/n/v1/linkitem/",LINK_HISTORY:"/n/v1/linkitemhistory/",LONG:"/n/v1/longitem/",LONG_HISTORY:"/n/v1/longitemhistory/",MARKDOWN:"/n/v1/markdownitem/",MARKDOWN_HISTORY:"/n/v1/markdownitemhistory/",MESSAGE_THREAD:"/n/v1/messagethread/",MESSAGE_THREAD_NOTIFICATION:"/n/v1/messagethreadnotification/",MONEY:"/n/v1/moneyitem/",MONEY_HISTORY:"/n/v1/moneyitemhistory/",OAUTH_TOKEN:"/n/v1/oauthtoken/",ORGANISATION:"/n/v1/organisation/",PAYMENT_INVOICE:"/n/v1/paymentinvoice/",PERMISSION:"/n/v1/permission/",PERSON:"/n/v1/person/",PERSON_NAME:"/n/v1/personname/",PROJECT:"/n/v1/project/",ROLE:"/n/v1/role/",SEARCH:"/n/v1/search/",STAT_SEATS:"/n/v1/stat/seats/",STAT_SIZE:"/n/v1/stat/size/",STAT_USAGE:"/n/v1/stat/usage/",REFERENCE:"/n/v1/referenceitem/",REFERENCE_HISTORY:"/n/v1/referenceitemhistory/",TASK:"/n/v1/task/",TASK_LOG:"/n/v1/tasklog/",TASK_LOGS:"/n/v1/tasklogs/",TELEPHONE:"/n/v1/telephone/",TEMPLATE:"/n/v1/templateitem/",TEMPLATE_HISTORY:"/n/v1/templateitemhistory/",TEXT:"/n/v1/textitem/",TEXT_HISTORY:"/n/v1/textitemhistory/",THREAD_POST:"/n/v1/threadpost/",WEBHOOK_SUBSCRIPTION:"/n/v1/webhooksubscription/",WEBHOOK_TRIGGER:"/n/v1/webhooktrigger/",WORKFLOW:"/n/v1/workflow/"});var e=class extends Error{status;statusText;body;method;url;requestBody;retryAfterMs;name="BaackApiError";constructor(t,i,s,r,o,E,a){super(`Baack API Error [${t}]: ${s||i}`),this.status=t,this.statusText=i,this.body=s,this.method=r,this.url=o,this.requestBody=E,this.retryAfterMs=a}heldUntil;get isUnauthorized(){return this.status===401}get isForbidden(){return this.status===403}get isNotFound(){return this.status===404}get isConflict(){return this.status===409||this.status===412}get isServerError(){return this.status>=500}get isRefused(){return this.status>=400&&this.status<500&&this.status!==408&&this.status!==429}get isInvalidRequest(){return T.has(this.status)}get isRetryable(){return this.status>=500||this.status===408||this.status===429}get apiError(){let t=this.json();return t!==null&&typeof t=="object"?t:void 0}get detail(){let t=this.apiError?.detail;return typeof t=="string"&&t!==""?t:void 0}json(){if(this.body)try{return JSON.parse(this.body)}catch{return}}},T=new Set([400,405,413,414,415,422,431]);function O(n){return n instanceof e}export{v as a,e as b,O as c};
|
|
2
|
+
//# sourceMappingURL=chunk-5RFN34CS.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../node_modules/@baack-software/baack-ts-client/src/endpoints.ts", "../../node_modules/@baack-software/baack-ts-client/src/errors.ts"],
|
|
4
|
+
"sourcesContent": ["export const Endpoint = Object.freeze({\n /** The session user's accounts (read only). */\n ACCOUNTS: '/n/v1/accounts',\n /**\n * The account setup form: a urlencoded POST (`BaackClient.submitForm`) that answers JSON when asked for it.\n * Without a URN it sets up a new account; `ACCOUNT_SETUP + '/' + urn` updates one.\n */\n ACCOUNT_SETUP: '/form/account-setup',\n /** Adds a user to an account company the session user administers: a form POST (`BaackClient.submitForm`). */\n ADD_USER: '/form/add-user',\n ADDRESS: '/n/v1/address/',\n API_CLIENT: '/n/v1/apiclient/',\n BEARER_TOKEN: '/n/v1/bearertoken/',\n BOOLEAN: '/n/v1/booleanitem/',\n BOOLEAN_HISTORY : '/n/v1/booleanitemhistory/',\n CLIENT_CONTEXT : '/n/v1/clientcontext',\n CLIENT_IDENTIFIER: '/n/v1/clientidentifier/',\n COMPANIES: '/n/v1/companies',\n COMPANY: '/n/v1/company/',\n DATE_TIME: '/n/v1/datetimeitem/',\n DATE_TIME_HISTORY: '/n/v1/datetimeitemhistory/',\n /** A deal sourced from a lead, which results in invoices when won. */\n DEAL: '/n/v1/deal/',\n DOUBLE: '/n/v1/doubleitem/',\n DOUBLE_HISTORY: '/n/v1/doubleitemhistory/',\n EMAIL: '/n/v1/email/',\n ENTITY: '/n/v1/entity/',\n ENTITY_LIST: '/n/v1/entitylist/',\n ENTITY_VIEW : '/v/v1/entityview/',\n GROUP: '/n/v1/group/',\n GROUP_MEMBERSHIP: '/n/v1/groupmembership/',\n IDENTITY: '/n/v1/identity/',\n IDENTITY_NOTIFICATION_INBOX: '/n/v1/identitynotificationinbox/',\n IMAGE: '/n/v1/imageitem/',\n IMAGE_HISTORY: '/n/v1/imageitemhistory/',\n IMAGE_FILE: '/n/v1/imageitemfile',\n /** A line of a payment invoice. */\n INVOICE_LINE: '/n/v1/invoiceline/',\n /** A payment received against a payment invoice, or a refund paid back. */\n INVOICE_REMITTANCE: '/n/v1/invoiceremittance/',\n JSON: '/n/v1/jsonitem/',\n JSON_HISTORY: '/n/v1/jsonitemhistory/',\n LAT_LONG: '/n/v1/latlongitem/',\n LAT_LONG_HISTORY: '/n/v1/latlongitemhistory/',\n /** A sales lead, for example a contact from a website form. A converted lead becomes a deal. */\n LEAD: '/n/v1/lead/',\n LINK: '/n/v1/linkitem/',\n LINK_HISTORY: '/n/v1/linkitemhistory/',\n LONG: '/n/v1/longitem/',\n LONG_HISTORY: '/n/v1/longitemhistory/',\n MARKDOWN: '/n/v1/markdownitem/',\n MARKDOWN_HISTORY: '/n/v1/markdownitemhistory/',\n MESSAGE_THREAD: '/n/v1/messagethread/',\n MESSAGE_THREAD_NOTIFICATION: '/n/v1/messagethreadnotification/',\n MONEY: '/n/v1/moneyitem/',\n MONEY_HISTORY: '/n/v1/moneyitemhistory/',\n OAUTH_TOKEN: '/n/v1/oauthtoken/',\n ORGANISATION: '/n/v1/organisation/',\n PAYMENT_INVOICE: '/n/v1/paymentinvoice/',\n PERMISSION: '/n/v1/permission/',\n PERSON: '/n/v1/person/',\n PERSON_NAME: '/n/v1/personname/',\n PROJECT: '/n/v1/project/',\n ROLE: '/n/v1/role/',\n SEARCH : '/n/v1/search/',\n STAT_SEATS: '/n/v1/stat/seats/',\n STAT_SIZE: '/n/v1/stat/size/',\n STAT_USAGE: '/n/v1/stat/usage/',\n REFERENCE: '/n/v1/referenceitem/',\n REFERENCE_HISTORY: '/n/v1/referenceitemhistory/',\n TASK: '/n/v1/task/',\n TASK_LOG: '/n/v1/tasklog/',\n TASK_LOGS: '/n/v1/tasklogs/',\n TELEPHONE: '/n/v1/telephone/',\n TEMPLATE: '/n/v1/templateitem/',\n TEMPLATE_HISTORY: '/n/v1/templateitemhistory/',\n TEXT: '/n/v1/textitem/',\n TEXT_HISTORY: '/n/v1/textitemhistory/',\n THREAD_POST: '/n/v1/threadpost/',\n WEBHOOK_SUBSCRIPTION: '/n/v1/webhooksubscription/',\n WEBHOOK_TRIGGER: '/n/v1/webhooktrigger/',\n WORKFLOW: '/n/v1/workflow/'\n});\n\n\n\n", "import type { ApiError } from './types/index.ts';\n\n/**\n * Thrown for any non-2xx response from the Baack API. Carries the HTTP status\n * so callers can tell an expired session (401) from a missing permission (403),\n * a conflict (409) or a server failure (5xx).\n *\n * Network failures (no response at all) are not wrapped: `fetch` rejects with\n * its own error, typically a `TypeError`.\n */\nexport class BaackApiError extends Error {\n override readonly name = 'BaackApiError';\n\n constructor(\n readonly status: number,\n readonly statusText: string,\n /** The raw response body, which may be a JSON error document or empty. */\n readonly body: string,\n readonly method: string,\n readonly url: string,\n /** The JSON body that was sent, when there was one, for debugging (not multipart uploads). */\n readonly requestBody?: string,\n /** How long the API asked callers to wait before trying again (its `Retry-After` header), when it said. */\n readonly retryAfterMs?: number,\n ) {\n super(`Baack API Error [${status}]: ${body || statusText}`);\n }\n\n /**\n * When the client's `failureGuard` holds this request back, the time (ms since the epoch) before which the same\n * request isn't sent again: until then it fails at once with this error. Use it to tell the user when to try again.\n */\n heldUntil?: number;\n\n get isUnauthorized(): boolean {\n return this.status === 401;\n }\n\n get isForbidden(): boolean {\n return this.status === 403;\n }\n\n get isNotFound(): boolean {\n return this.status === 404;\n }\n\n get isConflict(): boolean {\n return this.status === 409 || this.status === 412;\n }\n\n get isServerError(): boolean {\n return this.status >= 500;\n }\n\n /**\n * Whether the API refused the request: a 4xx other than a timeout (408) or rate limit (429). Some refusals depend\n * on state outside the request, such as an expired session (401) or a missing entity (404), and the same request\n * may succeed later; an invalid request (`isInvalidRequest`) never does.\n */\n get isRefused(): boolean {\n return this.status >= 400 && this.status < 500 && this.status !== 408 && this.status !== 429;\n }\n\n /**\n * Whether the request itself is invalid (400, 405, 413, 414, 415, 422 or 431), for example a missing required field\n * or an invalid representation; `apiError` says which. This is permanent: sending the same request again breaks the\n * contract again, so act on `apiError` (its `apiCode` and `detail`) or change the request, and never loop on it.\n */\n get isInvalidRequest(): boolean {\n return INVALID_REQUEST_STATUSES.has(this.status);\n }\n\n /** Whether the same request may succeed later: a server error, a timeout (408) or a rate limit (429). */\n get isRetryable(): boolean {\n return this.status >= 500 || this.status === 408 || this.status === 429;\n }\n\n /** The API error object from the body, when there is one. */\n get apiError(): ApiError | undefined {\n const parsed = this.json<ApiError>();\n return parsed !== null && typeof parsed === 'object' ? parsed : undefined;\n }\n\n /** The API's description of the problem, when it gave one. */\n get detail(): string | undefined {\n const detail = this.apiError?.detail;\n return typeof detail === 'string' && detail !== '' ? detail : undefined;\n }\n\n /** The body parsed as JSON, or undefined when it is empty or not JSON. */\n json<T = unknown>(): T | undefined {\n if (!this.body) return undefined;\n try {\n return JSON.parse(this.body) as T;\n } catch {\n return undefined;\n }\n }\n}\n\n/** Statuses that say the request itself is invalid, so sending it again unchanged gets the same answer. */\nconst INVALID_REQUEST_STATUSES = new Set([400, 405, 413, 414, 415, 422, 431]);\n\nexport function isBaackApiError(error: unknown): error is BaackApiError {\n return error instanceof BaackApiError;\n}\n"],
|
|
5
|
+
"mappings": "AAAO,IAAMA,EAAW,OAAO,OAAO,CAElC,SAAU,iBAKV,cAAe,sBAEf,SAAU,iBACV,QAAS,iBACT,WAAY,mBACZ,aAAc,qBACd,QAAS,qBACT,gBAAkB,4BAClB,eAAiB,sBACjB,kBAAmB,0BACnB,UAAW,kBACX,QAAS,iBACT,UAAW,sBACX,kBAAmB,6BAEnB,KAAM,cACN,OAAQ,oBACR,eAAgB,2BAChB,MAAO,eACP,OAAQ,gBACR,YAAa,oBACb,YAAc,oBACd,MAAO,eACP,iBAAkB,yBAClB,SAAU,kBACV,4BAA6B,mCAC7B,MAAO,mBACP,cAAe,0BACf,WAAY,sBAEZ,aAAc,qBAEd,mBAAoB,2BACpB,KAAM,kBACN,aAAc,yBACd,SAAU,qBACV,iBAAkB,4BAElB,KAAM,cACN,KAAM,kBACN,aAAc,yBACd,KAAM,kBACN,aAAc,yBACd,SAAW,sBACX,iBAAkB,6BAClB,eAAgB,uBAChB,4BAA6B,mCAC7B,MAAO,mBACP,cAAe,0BACf,YAAa,oBACb,aAAc,sBACd,gBAAiB,wBACjB,WAAY,oBACZ,OAAQ,gBACR,YAAa,oBACb,QAAS,iBACT,KAAM,cACN,OAAS,gBACT,WAAY,oBACZ,UAAW,mBACX,WAAY,oBACZ,UAAW,uBACX,kBAAmB,8BACnB,KAAM,cACN,SAAU,iBACV,UAAW,kBACX,UAAW,mBACX,SAAU,sBACV,iBAAkB,6BAClB,KAAM,kBACN,aAAc,yBACd,YAAa,oBACb,qBAAsB,6BACtB,gBAAiB,wBACjB,SAAU,kBACb,ECxEK,IAAOC,EAAP,cAA6B,KAAK,CAI3B,OACA,WAEA,KACA,OACA,IAEA,YAEA,aAZO,KAAO,gBAEzB,YACWC,EACAC,EAEAC,EACAC,EACAC,EAEAC,EAEAC,EAAqB,CAE9B,MAAM,oBAAoBN,CAAM,MAAME,GAAQD,CAAU,EAAE,EAXjD,KAAA,OAAAD,EACA,KAAA,WAAAC,EAEA,KAAA,KAAAC,EACA,KAAA,OAAAC,EACA,KAAA,IAAAC,EAEA,KAAA,YAAAC,EAEA,KAAA,aAAAC,CAGX,CAMA,UAEA,IAAI,gBAAc,CAChB,OAAO,KAAK,SAAW,GACzB,CAEA,IAAI,aAAW,CACb,OAAO,KAAK,SAAW,GACzB,CAEA,IAAI,YAAU,CACZ,OAAO,KAAK,SAAW,GACzB,CAEA,IAAI,YAAU,CACZ,OAAO,KAAK,SAAW,KAAO,KAAK,SAAW,GAChD,CAEA,IAAI,eAAa,CACf,OAAO,KAAK,QAAU,GACxB,CAOA,IAAI,WAAS,CACX,OAAO,KAAK,QAAU,KAAO,KAAK,OAAS,KAAO,KAAK,SAAW,KAAO,KAAK,SAAW,GAC3F,CAOA,IAAI,kBAAgB,CAClB,OAAOC,EAAyB,IAAI,KAAK,MAAM,CACjD,CAGA,IAAI,aAAW,CACb,OAAO,KAAK,QAAU,KAAO,KAAK,SAAW,KAAO,KAAK,SAAW,GACtE,CAGA,IAAI,UAAQ,CACV,IAAMC,EAAS,KAAK,KAAI,EACxB,OAAOA,IAAW,MAAQ,OAAOA,GAAW,SAAWA,EAAS,MAClE,CAGA,IAAI,QAAM,CACR,IAAMC,EAAS,KAAK,UAAU,OAC9B,OAAO,OAAOA,GAAW,UAAYA,IAAW,GAAKA,EAAS,MAChE,CAGA,MAAI,CACF,GAAK,KAAK,KACV,GAAI,CACF,OAAO,KAAK,MAAM,KAAK,IAAI,CAC7B,MAAQ,CACN,MACF,CACF,GAIIF,EAA2B,IAAI,IAAI,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,CAAC,EAEtE,SAAUG,EAAgBC,EAAc,CAC5C,OAAOA,aAAiBZ,CAC1B",
|
|
6
|
+
"names": ["Endpoint", "BaackApiError", "status", "statusText", "body", "method", "url", "requestBody", "retryAfterMs", "INVALID_REQUEST_STATUSES", "parsed", "detail", "isBaackApiError", "error"]
|
|
7
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function
|
|
1
|
+
import{a as y,b}from"./chunk-5RFN34CS.js";function q(){let r=document.querySelector('meta[name="baack-editor-api"]')?.content;return{...window.baackEditorConfig,baseUrl:window.baackEditorConfig?.baseUrl??r??"https://api.baack.co"}}var a=r=>["path",{d:r}],d=(r,e)=>["circle",{cx:r,cy:e,r:1}],C={"arrow-down":[a("M12 5v14"),a("m19 12-7 7-7-7")],"arrow-up":[a("m5 12 7-7 7 7"),a("M12 19V5")],check:[a("M20 6 9 17l-5-5")],"chevron-down":[a("m6 9 6 6 6-6")],"chevron-left":[a("m15 18-6-6 6-6")],"chevron-right":[a("m9 18 6-6-6-6")],ellipsis:[d(12,12),d(19,12),d(5,12)],"grip-vertical":[d(9,12),d(9,5),d(9,19),d(15,12),d(15,5),d(15,19)],history:[a("M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"),a("M3 3v5h5"),a("M12 7v5l4 2")],"list-ordered":[a("M10 12h11"),a("M10 18h11"),a("M10 6h11"),a("M4 10h2"),a("M4 6h1v4"),a("M6 18H4c0-1 2-2 2-3s-1-1.5-2-1")],"panel-left":[["rect",{width:18,height:18,x:3,y:3,rx:2}],a("M9 3v18")],"panel-right":[["rect",{width:18,height:18,x:3,y:3,rx:2}],a("M15 3v18")],"pencil-line":[a("M13 21h8"),a("m15 5 4 4"),a("M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z")],plus:[a("M5 12h14"),a("M12 5v14")],search:[["circle",{cx:11,cy:11,r:8}],a("m21 21-4.3-4.3")],x:[a("M18 6 6 18"),a("m6 6 12 12")]},M="http://www.w3.org/2000/svg";function S(r){let e=document.createElementNS(M,"svg");for(let[t,o]of Object.entries({viewBox:"0 0 24 24",width:16,height:16,fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round","aria-hidden":"true",focusable:"false",class:`icon icon-${r}`}))e.setAttribute(t,String(o));for(let[t,o]of C[r]){let n=document.createElementNS(M,t);for(let[l,s]of Object.entries(o))n.setAttribute(l,String(s));e.append(n)}return e}var k={background:"#ffffff",foreground:"#111827",popover:"#ffffff","popover-foreground":"#111827",primary:"#1d4ed8","primary-foreground":"#ffffff",secondary:"#f6f7f9","secondary-foreground":"#111827",muted:"#f6f7f9","muted-foreground":"#4b5563",accent:"#f3f4f6","accent-foreground":"#111827",destructive:"#dc2626","destructive-text":"#b91c1c",border:"#e5e7eb",input:"#d1d5db",ring:"#1d4ed8",success:"#047857",warning:"#92400e",preview:"#6d28d9",overlay:"rgb(0 0 0 / 0.5)","shadow-color":"rgb(17 24 39 / 0.1)","control-background":"var(--background)","control-border":"var(--border)","control-hover":"var(--muted)","field-background":"transparent","switch-off":"var(--input)","switch-thumb-off":"var(--background)","switch-thumb-on":"var(--background)"},h={background:"#0d1117",foreground:"#f3f4f6",popover:"#151b24","popover-foreground":"#f3f4f6",primary:"#6b9bff","primary-foreground":"#0d1117",secondary:"#1c2430","secondary-foreground":"#f3f4f6",muted:"#11161e","muted-foreground":"#a1a9b6",accent:"#1f2733","accent-foreground":"#f3f4f6",destructive:"#f87171","destructive-text":"#f87171",border:"#262e3a",input:"#343e4d",ring:"#6b9bff",success:"#34d399",warning:"#fbbf24",preview:"#c4b5fd",overlay:"rgb(0 0 0 / 0.65)","shadow-color":"rgb(0 0 0 / 0.45)","control-background":"color-mix(in oklab, var(--input) 30%, transparent)","control-border":"var(--input)","control-hover":"color-mix(in oklab, var(--input) 50%, transparent)","field-background":"color-mix(in oklab, var(--input) 30%, transparent)","switch-off":"color-mix(in oklab, var(--input) 80%, transparent)","switch-thumb-off":"var(--foreground)","switch-thumb-on":"var(--primary-foreground)"},B=`
|
|
2
2
|
/* Installed fonts only, so no site needs to allow a font source in its Content Security Policy. Figtree when the
|
|
3
3
|
page has loaded it (www.baack.co), then the nearest match on Apple devices, then each platform's UI font. */
|
|
4
4
|
--font-sans: Figtree, "Avenir Next", "Segoe UI Variable Text", "Segoe UI", Roboto, system-ui, -apple-system, sans-serif;
|
|
@@ -16,28 +16,21 @@ function L(){let t=document.querySelector('meta[name="baack-editor-api"]')?.cont
|
|
|
16
16
|
--shadow-lg: 0 10px 15px -3px var(--shadow-color), 0 4px 6px -4px var(--shadow-color);
|
|
17
17
|
/* shadcn's ring-3 ring-ring/50. */
|
|
18
18
|
--focus-ring: 0 0 0 3px color-mix(in oklab, var(--ring) 50%, transparent);
|
|
19
|
-
`;function
|
|
20
|
-
`)}var
|
|
19
|
+
`;function A(r){return Object.entries(r).map(([e,t])=>` --${e}: ${t};`).join(`
|
|
20
|
+
`)}var T=`
|
|
21
21
|
:host {
|
|
22
22
|
color-scheme: light;
|
|
23
|
-
${
|
|
24
|
-
${
|
|
23
|
+
${A(k)}
|
|
24
|
+
${B}
|
|
25
25
|
}
|
|
26
26
|
@media (prefers-color-scheme: dark) {
|
|
27
27
|
:host {
|
|
28
28
|
color-scheme: dark;
|
|
29
|
-
${
|
|
29
|
+
${A(h)}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.login-modal {
|
|
35
|
-
color-scheme: light;
|
|
36
|
-
${b(u)}
|
|
37
|
-
}
|
|
38
|
-
.login iframe { color-scheme: light; background: ${u.background}; }
|
|
39
|
-
`,C={primary:[u.primary,p.primary],warning:["#b45309",p.warning],preview:["#7c3aed",p.preview],success:[u.success,p.success],muted:["#6b7280","#9ca3af"]};var T="baack-editor-host",N=`${E}
|
|
40
|
-
:host { all: initial; }
|
|
32
|
+
`,$={primary:[k.primary,h.primary],warning:["#b45309",h.warning],preview:["#7c3aed",h.preview],success:[k.success,h.success],muted:["#6b7280","#9ca3af"]};var L="baack-editor-host",D=`:host { all: initial; }
|
|
33
|
+
${T}
|
|
41
34
|
* { box-sizing: border-box; }
|
|
42
35
|
.panel {
|
|
43
36
|
position: fixed; z-index: 2147483647;
|
|
@@ -57,8 +50,9 @@ ${b(u)}
|
|
|
57
50
|
.debug pre { margin: 4px 0 0; padding: 6px; max-height: 12em; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; background: var(--muted); border-radius: var(--radius-sm); font: 11px/1.45 var(--font-mono); }
|
|
58
51
|
.brand { font-weight: 700; letter-spacing: -0.01em; }
|
|
59
52
|
.pending { color: var(--warning); }
|
|
60
|
-
/* Buttons: shadcn/ui's variants and sizes (button() in this module). With no class, the outline variant.
|
|
61
|
-
button
|
|
53
|
+
/* Buttons: shadcn/ui's variants and sizes (button() in this module). With no class, the outline variant. A link
|
|
54
|
+
that acts as a button (the login link) has the class button. */
|
|
55
|
+
button, a.button {
|
|
62
56
|
display: inline-flex; align-items: center; justify-content: center; gap: 6px; flex-shrink: 0;
|
|
63
57
|
font: 500 var(--text-sm)/1.25 var(--font-sans); color: var(--foreground); cursor: pointer; user-select: none;
|
|
64
58
|
min-height: 32px; padding: 4px 10px; border-radius: var(--radius-lg);
|
|
@@ -67,11 +61,13 @@ button {
|
|
|
67
61
|
}
|
|
68
62
|
button:enabled:hover { background-color: var(--control-hover); color: var(--foreground); }
|
|
69
63
|
button:active:not([aria-haspopup]) { transform: translateY(1px); }
|
|
70
|
-
button
|
|
64
|
+
a.button { text-decoration: none; }
|
|
65
|
+
button:focus-visible, a.button:focus-visible { outline: none; border-color: var(--ring); box-shadow: var(--focus-ring); }
|
|
71
66
|
/* Not pointer-events: none, so the title saying why it is disabled still shows on hover. */
|
|
72
67
|
button:disabled { opacity: 0.5; cursor: default; }
|
|
73
68
|
button svg { flex-shrink: 0; width: 16px; height: 16px; pointer-events: none; }
|
|
74
|
-
button.primary { background: var(--primary); border-color: transparent; color: var(--primary-foreground); }
|
|
69
|
+
button.primary, a.button.primary { background: var(--primary); border-color: transparent; color: var(--primary-foreground); }
|
|
70
|
+
a.button.primary:hover,
|
|
75
71
|
button.primary:enabled:hover { background: color-mix(in oklab, var(--primary) 80%, transparent); }
|
|
76
72
|
button.secondary { background: var(--secondary); border-color: transparent; color: var(--secondary-foreground); }
|
|
77
73
|
button.secondary:enabled:hover { background: color-mix(in oklab, var(--secondary), var(--foreground) 5%); }
|
|
@@ -110,7 +106,8 @@ ul.issues { padding-left: 28px; }
|
|
|
110
106
|
.issues li { color: var(--foreground); }
|
|
111
107
|
/* A status line beside a field or in a list: coloured text, not a box. */
|
|
112
108
|
span.error, .hint.error { color: var(--destructive-text); }
|
|
113
|
-
.login
|
|
109
|
+
.login { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
110
|
+
.login > .message { flex-basis: 100%; }
|
|
114
111
|
.panel:not(.popover) { z-index: 2147483646; }
|
|
115
112
|
/* Below the editor's panels, so a popover or the sidebar covers the tags. */
|
|
116
113
|
.order-tag {
|
|
@@ -137,6 +134,7 @@ input, textarea, select {
|
|
|
137
134
|
transition: border-color 120ms, box-shadow 120ms;
|
|
138
135
|
}
|
|
139
136
|
select { cursor: pointer; }
|
|
137
|
+
option { background: var(--popover); color: var(--popover-foreground); }
|
|
140
138
|
input:focus-visible, textarea:focus-visible, select:focus-visible { outline: none; border-color: var(--ring); box-shadow: var(--focus-ring); }
|
|
141
139
|
input::placeholder, textarea::placeholder { color: var(--muted-foreground); }
|
|
142
140
|
input:disabled, textarea:disabled, select:disabled { opacity: 0.5; cursor: not-allowed; background: color-mix(in oklab, var(--input) 50%, transparent); }
|
|
@@ -184,11 +182,10 @@ input.switch:checked::before { background: var(--switch-thumb-on); transform: tr
|
|
|
184
182
|
.hint:empty { display: none; }
|
|
185
183
|
.popover[hidden], .login[hidden], .pending[hidden], [hidden] { display: none !important; }
|
|
186
184
|
.login-modal { position: fixed; inset: 0; z-index: 2147483647; background: var(--overlay); display: grid; place-items: center; }
|
|
187
|
-
/* shadcn/ui's dialog: a larger title, a muted description, then the
|
|
185
|
+
/* shadcn/ui's dialog: a larger title, a muted description, then the login link and its button. */
|
|
188
186
|
.panel.modal { position: static; width: min(440px, calc(100vw - 32px)); display: flex; flex-direction: column; gap: 16px; padding: 24px; border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); }
|
|
189
187
|
.modal > .title { font-size: 18px; line-height: 1.2; letter-spacing: -0.01em; }
|
|
190
188
|
.modal > p.message.info { padding: 0; border: 0; background: none; color: var(--muted-foreground); margin-top: -8px; }
|
|
191
|
-
.modal .login iframe { height: 320px; }
|
|
192
189
|
.pending { color: var(--warning); border-color: color-mix(in oklab, var(--warning) 40%, transparent); background: color-mix(in oklab, var(--warning) 10%, var(--background)); }
|
|
193
190
|
.rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
194
191
|
.row.problem { color: var(--destructive); }
|
|
@@ -284,6 +281,38 @@ button.row-main:active, .stack-row:active { transform: none; }
|
|
|
284
281
|
.row-name { font-weight: 600; }
|
|
285
282
|
.row-name.link { font-weight: 600; }
|
|
286
283
|
.outline .row.current { background: color-mix(in oklab, var(--primary) 8%, var(--popover)); box-shadow: inset 3px 0 0 var(--primary); }
|
|
284
|
+
/* Tasks (milestone 13): mini cards with space between them, a task's level in sections. */
|
|
285
|
+
.task-list { list-style: none; margin: 8px 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
286
|
+
.task-card {
|
|
287
|
+
display: flex; justify-content: flex-start; align-items: center; gap: 8px; width: 100%; min-height: 0; height: auto;
|
|
288
|
+
padding: 10px 12px; text-align: left; white-space: normal; font-weight: 400;
|
|
289
|
+
background: var(--popover); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
|
|
290
|
+
}
|
|
291
|
+
.task-card:hover { background: var(--accent); border-color: var(--input); }
|
|
292
|
+
.task-card:active { transform: none; }
|
|
293
|
+
.task-card-text { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
|
|
294
|
+
.task-title { font-weight: 600; color: var(--foreground); }
|
|
295
|
+
.task-facts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: var(--text-xs); }
|
|
296
|
+
.task-assignee { display: inline-flex; align-items: center; gap: 4px; }
|
|
297
|
+
.avatar { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex-shrink: 0; border-radius: 999px; font: 600 10px/1 var(--font-sans); }
|
|
298
|
+
.avatar-0 { background: color-mix(in oklab, var(--primary) 16%, var(--popover)); color: var(--primary); }
|
|
299
|
+
.avatar-1 { background: color-mix(in oklab, var(--success) 16%, var(--popover)); color: var(--success); }
|
|
300
|
+
.avatar-2 { background: color-mix(in oklab, var(--warning) 16%, var(--popover)); color: var(--warning); }
|
|
301
|
+
.avatar-3 { background: color-mix(in oklab, var(--preview) 16%, var(--popover)); color: var(--preview); }
|
|
302
|
+
.avatar-4 { background: color-mix(in oklab, var(--destructive) 14%, var(--popover)); color: var(--destructive-text); }
|
|
303
|
+
.avatar-5 { background: var(--secondary); color: var(--secondary-foreground); }
|
|
304
|
+
.task-status.tone-active { background: color-mix(in oklab, var(--primary) 12%, var(--popover)); color: var(--primary); }
|
|
305
|
+
.task-status.tone-danger { background: color-mix(in oklab, var(--destructive) 10%, var(--popover)); color: var(--destructive-text); }
|
|
306
|
+
.task-status.tone-success { background: transparent; border-color: var(--success); color: var(--success); }
|
|
307
|
+
.task-status.tone-muted { color: var(--muted-foreground); }
|
|
308
|
+
.level-tasks > .actions { margin-top: 4px; }
|
|
309
|
+
.level-task { display: flex; flex-direction: column; gap: 14px; }
|
|
310
|
+
.task-description { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
311
|
+
.task-section { display: flex; flex-direction: column; gap: 6px; }
|
|
312
|
+
.task-activity { list-style: none; margin: 0; padding: 0; }
|
|
313
|
+
.task-entry { padding: 6px 0; border-bottom: 1px solid var(--border); }
|
|
314
|
+
.task-entry-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; font-size: var(--text-xs); }
|
|
315
|
+
.task-comment { margin: 4px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
287
316
|
/* Badges: shadcn/ui's badge, for lifecycle and item states. Secondary unless the state says otherwise. */
|
|
288
317
|
.status, .flag {
|
|
289
318
|
display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0; white-space: nowrap;
|
|
@@ -336,5 +365,5 @@ button.row-main:active, .stack-row:active { transform: none; }
|
|
|
336
365
|
.actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
|
|
337
366
|
.actions > button { white-space: nowrap; }
|
|
338
367
|
.hint { margin: 0; color: var(--muted-foreground); font-size: var(--text-xs); }
|
|
339
|
-
`;function
|
|
340
|
-
//# sourceMappingURL=chunk-
|
|
368
|
+
`;function J(){let r=document.getElementById(L);r||(r=document.createElement("div"),r.id=L,r.attachShadow({mode:"open"}),document.body.append(r));let e=r.shadowRoot;if(!e.querySelector("style")){let t=document.createElement("style");t.textContent=D,e.append(t)}return{element:r,root:e}}function Y(r){if(!r)return[];let e=i("details","debug");return e.append(i("summary","","Debug"),i("pre","",r)),[e]}function X(r,e="outline",t="default",o=""){let n=[o,e==="outline"?"":e,t==="default"?"":t].filter(Boolean).join(" "),l=i("button",n,r);return l.type="button",l}function Q(r){return r.destructive?"destructive":r.primary?"primary":"outline"}function Z(r){let e=i("span","select-box");return e.append(r,S("chevron-down")),e}function i(r,e="",t=""){let o=document.createElement(r);return e&&(o.className=e),t&&(o.textContent=t),o}var I="Edit page";function re(r){let e=r.root.querySelector(".toolbar button.mode");if(e)return e;let t=i("div","panel toolbar");t.setAttribute("role","region"),t.setAttribute("aria-label","Baack editor");let o=i("div","toolbar-row"),n=i("button","mode",I);return n.type="button",n.setAttribute("aria-pressed","false"),o.append(i("span","brand","Baack"),n),t.append(o),r.root.append(t),n}var z="baack-login",N="popup,width=480,height=640";function ne(r,e="Log in to Baack"){let t=i("a","button primary",e);t.href=r,t.target=z;let o=null;return t.addEventListener("click",n=>{o=window.open(r,z,N),o&&(n.preventDefault(),o.focus())}),{element:t,close:()=>{o&&!o.closed&&o.close(),o=null}}}function ie(r){let e=()=>{document.visibilityState==="visible"&&r()};return window.addEventListener("focus",r),document.addEventListener("visibilitychange",e),()=>{window.removeEventListener("focus",r),document.removeEventListener("visibilitychange",e)}}var U={refusedHoldMs:3e5,backoffMs:1e3,maxBackoffMs:6e4},j=500,F=.2,p={CREATE:"POST",READ:"GET",UPDATE:"PUT",DELETE:"DELETE"},H=class{baseUrl;defaultHeaders;credentials;guard;failed=new Map;constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.defaultHeaders={...e.headers},this.credentials=e.credentials,this.guard=e.failureGuard===!1?void 0:{...U,...e.failureGuard}}async request(e,t={},o){let n=new URL(this.baseUrl+e);o&&Object.entries(o).forEach(([f,c])=>{c!=null&&n.searchParams.append(f,String(c))});let l=typeof t.body=="string"?{"Content-Type":"application/json",...this.defaultHeaders}:{...this.defaultHeaders},s={...t,headers:{...l,...t.headers}};this.credentials&&(s.credentials=this.credentials);let m=t.method??p.READ,u=typeof s.body=="string"?s.body:void 0,x=s.body===void 0||u!==void 0?`${m} ${n.toString()} ${u??""} ${P(t.headers)}`:void 0,v=this.guard&&x!==void 0&&this.failed.get(x);if(v&&Date.now()<v.until)throw v.error;let g;try{g=await fetch(n.toString(),s)}catch(f){throw this.recordFailure(x,f,!1),f}let w=await g.text();if(!g.ok){let f=O(g.headers.get("Retry-After")),c=new b(g.status,g.statusText,w,m,n.toString(),u,f);throw this.recordFailure(x,c,c.isInvalidRequest),c}return x!==void 0&&this.failed.delete(x),w?JSON.parse(w):void 0}recordFailure(e,t,o){if(!this.guard||e===void 0)return;let n=(this.failed.get(e)?.failures??0)+1,l=Math.min(this.guard.backoffMs*2**(n-1),this.guard.maxBackoffMs),s=t instanceof b?t.retryAfterMs??0:0,m=Math.max(o?this.guard.refusedHoldMs:l*(1+Math.random()*F),s),u=Date.now()+m;t instanceof b&&(t.heldUntil=u),this.failed.delete(e),this.failed.set(e,{error:t,until:u,failures:n}),this.failed.size>j&&this.failed.delete(this.failed.keys().next().value)}async create(e,t,o){return this.request(e,R(p.CREATE,t,o))}async read(e,t,o,n){return this.request(E(e,t),{method:p.READ,...n?{headers:n}:{}},o)}async update(e,t,o,n){return this.request(E(e,t),R(p.UPDATE,o,n))}async delete(e,t,o){return this.request(E(e,t),{method:p.DELETE,...o?{headers:o}:{}})}async upload(e,t){return this.request(e,{method:p.CREATE,body:t})}async submitForm(e,t,o){return this.request(e,{method:p.CREATE,body:t.toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",...o}})}async search(e){return this.create(y.SEARCH,e)}async searchResult(e,t){return this.read(y.SEARCH,e,{after:t})}};function E(r,e){return r.endsWith("/")&&e.startsWith("/")?r+e.slice(1):r+e}function P(r){return r?JSON.stringify(Object.entries(r).sort(([e],[t])=>e.localeCompare(t))):""}function O(r){if(r===null||r.trim()==="")return;let e=Number(r);if(Number.isFinite(e))return e>=0?e*1e3:void 0;let t=Date.parse(r);return Number.isNaN(t)?void 0:Math.max(0,t-Date.now())}function R(r,e,t){let o=e===void 0?{method:r}:{method:r,body:JSON.stringify(e)};return t?{...o,headers:t}:o}export{q as a,H as b,S as c,$ as d,J as e,Y as f,X as g,Q as h,Z as i,i as j,re as k,ne as l,ie as m};
|
|
369
|
+
//# sourceMappingURL=chunk-MSWF55NC.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/config.ts", "../../src/ui/icons.ts", "../../src/ui/theme.ts", "../../src/ui/host.ts", "../../src/ui/launcher.ts", "../../src/ui/login-window.ts", "../../node_modules/@baack-software/baack-ts-client/src/client.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AfterPublish } from './after-publish.ts';\nimport type { EntityNameForPage, PagePathForEntity } from './page-entity.ts';\n\n// Site configuration, set before the loader runs:\n// <script>window.baackEditorConfig = { baseUrl: 'https://api.baack.co' }</script>\n\nexport interface EditorConfig {\n /** Where the Baack API is. Requests carry the user's session cookie. */\n baseUrl: string;\n /** How long a publish may stay in progress before the editor says it is taking too long. Default 5 minutes. */\n publishTimeoutMs?: number;\n /** Image slots a version needs before its entity can be published. Default: the default slot only. */\n requiredImageSlots?: ('DEFAULT' | 'MEDIUM' | 'LARGE')[];\n /**\n * Off by default. Widths to create the medium and large files at, in the\n * browser, when only a default file is chosen. Never scales up.\n */\n imageWidths?: { MEDIUM?: number; LARGE?: number };\n /** Largest image file the editor will upload, in bytes. Default 10 MB. */\n maxImageBytes?: number;\n /** Above this size the editor warns that the file is large for the web. Default 2 MB. */\n warnImageBytes?: number;\n /**\n * After every publish (an entity, or a version from History): a message to\n * show, such as \"Live after the next build, in about 2 minutes\", or a\n * function called with what was published, which may return a message.\n * Fixed text also replaces the note about built sites on leaving edit mode.\n */\n afterPublish?: AfterPublish;\n /**\n * The entity name that serves a page whose markup names no entity, from\n * the page's URL path: used to find its content, and offered when creating\n * it. Baack has no index entities, so a directory path needs a name of its\n * own. Default: `/` (and `/index.html`) is `/home`, otherwise the path\n * without a trailing slash.\n */\n entityNameForPage?: EntityNameForPage;\n /**\n * The reverse: the page address an entity serves, from its name. Used for\n * a link's suggestions and the `path` told to `afterPublish`. Default:\n * `/home` is `/`, any other name its own path.\n */\n pagePathForEntity?: PagePathForEntity;\n /**\n * Where \"Edit page\" is. `floating` (the default): the editor's own button, in the bottom corner. `page`: the page\n * has its own, on any element with `data-baack-editor-launch`, such as an Edit button in an admin page's header.\n * It starts editing at once (or opens the login), and ends it when pressed again; the editor keeps\n * `aria-pressed` on it up to date. The editor's toolbar then shows only while editing, so nothing floats over the\n * page's own controls otherwise.\n */\n launcher?: 'floating' | 'page';\n}\n\ndeclare global {\n interface Window {\n baackEditorConfig?: Partial<EditorConfig>;\n }\n}\n\n/**\n * The configuration, from `window.baackEditorConfig`, or (for sites whose\n * Content-Security-Policy forbids inline scripts) a meta tag:\n * <meta name=\"baack-editor-api\" content=\"https://api.baack.co\">\n */\nexport function readConfig(): EditorConfig {\n const meta = document.querySelector<HTMLMetaElement>('meta[name=\"baack-editor-api\"]')?.content;\n return { ...window.baackEditorConfig, baseUrl: window.baackEditorConfig?.baseUrl ?? meta ?? 'https://api.baack.co' };\n}\n", "// The editor's icons: a few from lucide (https://lucide.dev, ISC licence),\n// copied as shapes and drawn with DOM calls, so there is no package and no\n// markup parsed. 24 by 24, stroked in currentColor, as lucide draws them.\n\ntype Shape = [tag: 'path' | 'circle' | 'rect', attributes: Record<string, string | number>];\n\nconst path = (d: string): Shape => ['path', { d }];\nconst dot = (cx: number, cy: number): Shape => ['circle', { cx, cy, r: 1 }];\n\nconst ICONS = {\n 'arrow-down': [path('M12 5v14'), path('m19 12-7 7-7-7')],\n 'arrow-up': [path('m5 12 7-7 7 7'), path('M12 19V5')],\n check: [path('M20 6 9 17l-5-5')],\n 'chevron-down': [path('m6 9 6 6 6-6')],\n 'chevron-left': [path('m15 18-6-6 6-6')],\n 'chevron-right': [path('m9 18 6-6-6-6')],\n ellipsis: [dot(12, 12), dot(19, 12), dot(5, 12)],\n 'grip-vertical': [dot(9, 12), dot(9, 5), dot(9, 19), dot(15, 12), dot(15, 5), dot(15, 19)],\n history: [path('M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8'), path('M3 3v5h5'), path('M12 7v5l4 2')],\n 'list-ordered': [path('M10 12h11'), path('M10 18h11'), path('M10 6h11'), path('M4 10h2'), path('M4 6h1v4'), path('M6 18H4c0-1 2-2 2-3s-1-1.5-2-1')],\n 'panel-left': [['rect', { width: 18, height: 18, x: 3, y: 3, rx: 2 }], path('M9 3v18')],\n 'panel-right': [['rect', { width: 18, height: 18, x: 3, y: 3, rx: 2 }], path('M15 3v18')],\n 'pencil-line': [path('M13 21h8'), path('m15 5 4 4'), path('M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z')],\n plus: [path('M5 12h14'), path('M12 5v14')],\n search: [['circle', { cx: 11, cy: 11, r: 8 }], path('m21 21-4.3-4.3')],\n x: [path('M18 6 6 18'), path('m6 6 12 12')],\n} satisfies Record<string, Shape[]>;\n\nexport type IconName = keyof typeof ICONS;\n\nconst SVG = 'http://www.w3.org/2000/svg';\n\n/** An icon, hidden from assistive technology: the control it sits in carries the name. */\nexport function icon(name: IconName): SVGSVGElement {\n const svg = document.createElementNS(SVG, 'svg');\n for (const [attribute, value] of Object.entries({\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'none',\n stroke: 'currentColor',\n 'stroke-width': 2,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n 'aria-hidden': 'true',\n focusable: 'false',\n class: `icon icon-${name}`,\n })) {\n svg.setAttribute(attribute, String(value));\n }\n for (const [tag, attributes] of ICONS[name] as Shape[]) {\n const shape = document.createElementNS(SVG, tag);\n for (const [attribute, value] of Object.entries(attributes)) shape.setAttribute(attribute, String(value));\n svg.append(shape);\n }\n return svg;\n}\n", "// The Baack look (docs/plans/baack-look.md): www.baack.co's shadcn/ui tokens\n// as CSS custom properties on the editor's shadow host, light and dark. The\n// editor's stylesheet (host.ts) uses only these: no literal colours.\n//\n// Sizes are in px, not rem: rem follows the host page's root font size.\n\nconst LIGHT = {\n background: '#ffffff',\n foreground: '#111827',\n popover: '#ffffff',\n 'popover-foreground': '#111827',\n primary: '#1d4ed8',\n 'primary-foreground': '#ffffff',\n secondary: '#f6f7f9',\n 'secondary-foreground': '#111827',\n muted: '#f6f7f9',\n 'muted-foreground': '#4b5563',\n accent: '#f3f4f6',\n 'accent-foreground': '#111827',\n destructive: '#dc2626',\n // Red text on a red tint (destructive buttons, badges): darker, for 4.5:1 contrast.\n 'destructive-text': '#b91c1c',\n border: '#e5e7eb',\n input: '#d1d5db',\n ring: '#1d4ed8',\n success: '#047857',\n // The site's amber tone: unsaved and pending work.\n warning: '#92400e',\n // The site's violet tone: previews of other versions.\n preview: '#6d28d9',\n overlay: 'rgb(0 0 0 / 0.5)',\n 'shadow-color': 'rgb(17 24 39 / 0.1)',\n // The outline button and fields: shadcn's light and dark treatments differ.\n 'control-background': 'var(--background)',\n 'control-border': 'var(--border)',\n 'control-hover': 'var(--muted)',\n 'field-background': 'transparent',\n 'switch-off': 'var(--input)',\n 'switch-thumb-off': 'var(--background)',\n 'switch-thumb-on': 'var(--background)',\n};\n\nconst DARK: typeof LIGHT = {\n background: '#0d1117',\n foreground: '#f3f4f6',\n popover: '#151b24',\n 'popover-foreground': '#f3f4f6',\n primary: '#6b9bff',\n 'primary-foreground': '#0d1117',\n secondary: '#1c2430',\n 'secondary-foreground': '#f3f4f6',\n muted: '#11161e',\n 'muted-foreground': '#a1a9b6',\n accent: '#1f2733',\n 'accent-foreground': '#f3f4f6',\n destructive: '#f87171',\n 'destructive-text': '#f87171',\n border: '#262e3a',\n input: '#343e4d',\n ring: '#6b9bff',\n success: '#34d399',\n warning: '#fbbf24',\n preview: '#c4b5fd',\n overlay: 'rgb(0 0 0 / 0.65)',\n 'shadow-color': 'rgb(0 0 0 / 0.45)',\n 'control-background': 'color-mix(in oklab, var(--input) 30%, transparent)',\n 'control-border': 'var(--input)',\n 'control-hover': 'color-mix(in oklab, var(--input) 50%, transparent)',\n 'field-background': 'color-mix(in oklab, var(--input) 30%, transparent)',\n 'switch-off': 'color-mix(in oklab, var(--input) 80%, transparent)',\n 'switch-thumb-off': 'var(--foreground)',\n 'switch-thumb-on': 'var(--primary-foreground)',\n};\n\nconst SCALE = `\n /* Installed fonts only, so no site needs to allow a font source in its Content Security Policy. Figtree when the\n page has loaded it (www.baack.co), then the nearest match on Apple devices, then each platform's UI font. */\n --font-sans: Figtree, \"Avenir Next\", \"Segoe UI Variable Text\", \"Segoe UI\", Roboto, system-ui, -apple-system, sans-serif;\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n --text-xs: 12px;\n --text-sm: 14px;\n --text-base: 16px;\n --radius: 10px;\n --radius-sm: 6px;\n --radius-md: 8px;\n --radius-lg: 10px;\n --radius-xl: 14px;\n --shadow-sm: 0 1px 2px 0 var(--shadow-color);\n --shadow-md: 0 4px 6px -1px var(--shadow-color), 0 2px 4px -2px var(--shadow-color);\n --shadow-lg: 0 10px 15px -3px var(--shadow-color), 0 4px 6px -4px var(--shadow-color);\n /* shadcn's ring-3 ring-ring/50. */\n --focus-ring: 0 0 0 3px color-mix(in oklab, var(--ring) 50%, transparent);\n`;\n\nfunction tokens(set: typeof LIGHT): string {\n return Object.entries(set)\n .map(([name, value]) => ` --${name}: ${value};`)\n .join('\\n');\n}\n\n/** The tokens, for the start of the shadow root's stylesheet. Dark follows the visitor's system setting. */\nexport const THEME_CSS = `\n:host {\n color-scheme: light;\n${tokens(LIGHT)}\n${SCALE}\n}\n@media (prefers-color-scheme: dark) {\n :host {\n color-scheme: dark;\n${tokens(DARK)}\n }\n}\n`;\n\n/**\n * Outline colours for elements on the host page, outside the shadow root: each is light-dark(), so it follows the\n * page's own color-scheme, with the light colour for browsers without light-dark().\n */\nexport const PAGE_COLOURS = {\n primary: [LIGHT.primary, DARK.primary],\n warning: ['#b45309', DARK.warning],\n preview: ['#7c3aed', DARK.preview],\n success: [LIGHT.success, DARK.success],\n muted: ['#6b7280', '#9ca3af'],\n} as const satisfies Record<string, readonly [string, string]>;\n", "// The editor's own corner of the page: one element with a shadow root, so\n// host page CSS cannot reach the editor UI and the editor's CSS cannot leak.\n\nimport { icon } from './icons.ts';\nimport { THEME_CSS } from './theme.ts';\n\nconst HOST_ID = 'baack-editor-host';\n\n// The reset comes before the theme: \\`all: initial\\` would otherwise reset the\n// theme's color-scheme, and native dropdowns would draw light in dark mode.\nconst STYLES = `:host { all: initial; }\n${THEME_CSS}\n* { box-sizing: border-box; }\n.panel {\n position: fixed; z-index: 2147483647;\n font: var(--text-sm)/1.45 var(--font-sans);\n color: var(--popover-foreground); background: var(--popover);\n border: 1px solid var(--border); border-radius: var(--radius-lg);\n box-shadow: var(--shadow-md);\n padding: 10px 12px;\n}\n.toolbar { right: 16px; bottom: 16px; display: flex; flex-direction: column; gap: 6px; max-width: 380px; }\n/* A row wraps whole buttons onto the next line rather than squeezing their labels. */\n.toolbar-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }\n.toolbar-row > button, .toolbar-row > .brand { white-space: nowrap; }\n.toolbar > .message-action { align-self: flex-start; }\n.debug { font-size: var(--text-xs); color: var(--muted-foreground); }\n.debug summary { cursor: pointer; }\n.debug pre { margin: 4px 0 0; padding: 6px; max-height: 12em; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; background: var(--muted); border-radius: var(--radius-sm); font: 11px/1.45 var(--font-mono); }\n.brand { font-weight: 700; letter-spacing: -0.01em; }\n.pending { color: var(--warning); }\n/* Buttons: shadcn/ui's variants and sizes (button() in this module). With no class, the outline variant. A link\n that acts as a button (the login link) has the class button. */\nbutton, a.button {\n display: inline-flex; align-items: center; justify-content: center; gap: 6px; flex-shrink: 0;\n font: 500 var(--text-sm)/1.25 var(--font-sans); color: var(--foreground); cursor: pointer; user-select: none;\n min-height: 32px; padding: 4px 10px; border-radius: var(--radius-lg);\n border: 1px solid var(--control-border); background: var(--control-background); background-clip: padding-box;\n transition: background-color 120ms, border-color 120ms, box-shadow 120ms, color 120ms;\n}\nbutton:enabled:hover { background-color: var(--control-hover); color: var(--foreground); }\nbutton:active:not([aria-haspopup]) { transform: translateY(1px); }\na.button { text-decoration: none; }\nbutton:focus-visible, a.button:focus-visible { outline: none; border-color: var(--ring); box-shadow: var(--focus-ring); }\n/* Not pointer-events: none, so the title saying why it is disabled still shows on hover. */\nbutton:disabled { opacity: 0.5; cursor: default; }\nbutton svg { flex-shrink: 0; width: 16px; height: 16px; pointer-events: none; }\nbutton.primary, a.button.primary { background: var(--primary); border-color: transparent; color: var(--primary-foreground); }\na.button.primary:hover,\nbutton.primary:enabled:hover { background: color-mix(in oklab, var(--primary) 80%, transparent); }\nbutton.secondary { background: var(--secondary); border-color: transparent; color: var(--secondary-foreground); }\nbutton.secondary:enabled:hover { background: color-mix(in oklab, var(--secondary), var(--foreground) 5%); }\nbutton.ghost { background: transparent; border-color: transparent; }\nbutton.ghost:enabled:hover { background: var(--control-hover); }\nbutton.destructive { background: color-mix(in oklab, var(--destructive) 10%, transparent); border-color: transparent; color: var(--destructive-text); }\nbutton.destructive:enabled:hover { background: color-mix(in oklab, var(--destructive) 20%, transparent); }\nbutton.destructive:focus-visible { border-color: color-mix(in oklab, var(--destructive) 40%, transparent); box-shadow: 0 0 0 3px color-mix(in oklab, var(--destructive) 20%, transparent); }\n/* A link inside text: no box, so it sits in the line. */\nbutton.link { display: inline; min-height: 0; padding: 0; border: 0; border-radius: var(--radius-sm); background: none; font: inherit; color: var(--primary); text-decoration: underline; text-underline-offset: 4px; }\nbutton.link:hover { background: none; text-decoration-thickness: 2px; }\nbutton.link:active { transform: none; }\nbutton.xs { min-height: 24px; gap: 4px; padding: 2px 8px; font-size: var(--text-xs); border-radius: var(--radius-md); }\nbutton.xs svg { width: 12px; height: 12px; }\nbutton.sm { min-height: 28px; gap: 4px; padding: 2px 10px; font-size: 12.8px; border-radius: var(--radius-md); }\nbutton.sm svg { width: 14px; height: 14px; }\nbutton.lg { min-height: 36px; }\nbutton.icon, button.icon-sm, button.icon-xs { padding: 0; width: 32px; height: 32px; min-height: 0; }\nbutton.icon-sm { width: 28px; height: 28px; border-radius: var(--radius-md); }\nbutton.icon-xs { width: 24px; height: 24px; border-radius: var(--radius-md); }\nbutton.icon-xs svg { width: 12px; height: 12px; }\n/* A toggle that is on, such as the live-page preview. */\nbutton[aria-pressed=\"true\"] { background: color-mix(in oklab, var(--primary) 10%, var(--control-background)); border-color: color-mix(in oklab, var(--primary) 60%, transparent); color: var(--primary); }\n/* Messages: shadcn/ui's alert. The colour is in the border and tint; the text keeps full contrast. */\n.message:empty, .issues:empty, .error:empty { display: none; }\np.message, p.error, .issues {\n margin: 0; padding: 8px 12px; border-radius: var(--radius-lg); font-size: var(--text-sm); color: var(--foreground);\n border: 1px solid color-mix(in oklab, var(--destructive) 50%, transparent);\n background: color-mix(in oklab, var(--destructive) 5%, var(--popover));\n}\np.message.info { border-color: var(--border); background: var(--popover); }\n.issues { padding-left: 12px; border-color: color-mix(in oklab, var(--warning) 45%, transparent); background: color-mix(in oklab, var(--warning) 6%, var(--popover)); }\nul.issues { padding-left: 28px; }\n.issues li::marker { color: var(--warning); }\n.issues li.error::marker { color: var(--destructive); }\n.issues li { color: var(--foreground); }\n/* A status line beside a field or in a list: coloured text, not a box. */\nspan.error, .hint.error { color: var(--destructive-text); }\n.login { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }\n.login > .message { flex-basis: 100%; }\n.panel:not(.popover) { z-index: 2147483646; }\n/* Below the editor's panels, so a popover or the sidebar covers the tags. */\n.order-tag {\n position: fixed; z-index: 2147483645; min-height: 0;\n font: 500 var(--text-xs)/1.3 var(--font-sans); color: var(--foreground);\n padding: 2px 8px; border-radius: 999px; border: 1px solid var(--border);\n background: color-mix(in oklab, var(--background) 94%, transparent); box-shadow: var(--shadow-sm);\n}\n.popover { width: max-content; min-width: 240px; max-width: 360px; display: flex; flex-direction: column; gap: 10px; padding: 12px 14px; }\n.popover.wide { width: min(560px, calc(100vw - 16px)); max-width: none; }\n/* Never taller than the window: what doesn't fit scrolls inside the panel, on its background. */\n.popover { max-height: calc(100vh - 16px); overflow-y: auto; }\n.form:empty { display: none; }\n.form { display: flex; flex-direction: column; gap: 10px; }\n.field { display: flex; flex-direction: column; gap: 6px; }\n.field.checkbox { flex-direction: row; align-items: center; gap: 8px; cursor: pointer; }\n/* A field's label: shadcn/ui's label. A caption over a value shown read-only stays small and muted. */\n.caption { color: var(--muted-foreground); font-size: var(--text-xs); font-weight: 500; }\n.field > .caption, .field.checkbox .caption { color: var(--foreground); font-size: var(--text-sm); line-height: 1; }\n/* Fields: shadcn/ui's input, textarea and select. */\ninput, textarea, select {\n font: var(--text-sm)/1.4 var(--font-sans); color: var(--foreground); background: var(--field-background);\n min-width: 0; min-height: 32px; border: 1px solid var(--input); border-radius: var(--radius-lg); padding: 4px 10px;\n transition: border-color 120ms, box-shadow 120ms;\n}\nselect { cursor: pointer; }\noption { background: var(--popover); color: var(--popover-foreground); }\ninput:focus-visible, textarea:focus-visible, select:focus-visible { outline: none; border-color: var(--ring); box-shadow: var(--focus-ring); }\ninput::placeholder, textarea::placeholder { color: var(--muted-foreground); }\ninput:disabled, textarea:disabled, select:disabled { opacity: 0.5; cursor: not-allowed; background: color-mix(in oklab, var(--input) 50%, transparent); }\n[aria-invalid=\"true\"] { border-color: var(--destructive); box-shadow: 0 0 0 3px color-mix(in oklab, var(--destructive) 20%, transparent); }\ntextarea { resize: vertical; width: 100%; }\ninput[type=\"file\"] { min-height: 0; padding: 4px; }\ninput[type=\"file\"]::file-selector-button {\n font: 500 var(--text-sm) var(--font-sans); color: var(--foreground); cursor: pointer; margin-right: 8px;\n padding: 3px 10px; border: 1px solid var(--control-border); border-radius: var(--radius-md); background: var(--control-background);\n}\ninput[type=\"checkbox\"]:not(.switch) { min-height: 0; accent-color: var(--primary); }\n/* A switch: a checkbox with role=\"switch\", drawn as shadcn/ui's. */\ninput.switch {\n appearance: none; position: relative; flex-shrink: 0; cursor: pointer; margin: 0; padding: 0;\n width: 32px; height: 18.4px; min-height: 0; border-radius: 999px; border: 1px solid transparent; background: var(--switch-off);\n transition: background-color 150ms, box-shadow 120ms;\n}\ninput.switch::before {\n content: \"\"; position: absolute; top: 50%; left: 0; width: 16px; height: 16px; border-radius: 999px;\n background: var(--switch-thumb-off); transform: translate(0, -50%); transition: transform 150ms;\n}\ninput.switch:checked { background: var(--primary); }\ninput.switch:checked::before { background: var(--switch-thumb-on); transform: translate(14px, -50%); }\n/* iOS Safari zooms into a field under 16px as it takes focus. */\n@media (max-width: 767px) { input, textarea, select { font-size: var(--text-base); } }\n/* The entity picker: a combo box with its list below. */\n.entity-picker { display: flex; flex-direction: column; gap: 4px; }\n/* shadcn/ui's combobox (its Command list): a search field, then the options. */\n.combobox-field, .select-box { position: relative; display: flex; flex-direction: column; }\n.combobox-field > svg, .select-box > svg { position: absolute; top: 50%; transform: translateY(-50%); pointer-events: none; color: var(--muted-foreground); }\n.combobox-field > svg:first-child { left: 10px; }\n.combobox-field > svg:last-child, .select-box > svg { right: 10px; }\n.combobox-field > input { padding-left: 32px; padding-right: 32px; }\n.select-box > select { appearance: none; padding-right: 32px; }\n.entity-options { list-style: none; margin: 0; padding: 4px; border: 1px solid var(--border); border-radius: var(--radius-lg); max-height: 220px; overflow: auto; background: var(--popover); box-shadow: var(--shadow-md); }\n.entity-option { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-radius: var(--radius-sm); cursor: pointer; overflow-wrap: anywhere; }\n.entity-option > .meta { flex: 1 1 auto; }\n.entity-option > svg { flex-shrink: 0; }\n.entity-option:hover, .entity-option.active { background: var(--accent); color: var(--accent-foreground); }\n.entity-option[aria-selected=\"true\"] { font-weight: 500; }\n.entity-option.create { margin-top: 4px; border-top: 1px solid var(--border); border-radius: 0 0 var(--radius-sm) var(--radius-sm); }\n.entity-create:empty { display: none; }\n.entity-create { border-top: 1px solid var(--border); padding-top: 6px; }\n.field.code textarea { font: var(--text-xs)/1.45 var(--font-mono); }\n.hint:empty { display: none; }\n.popover[hidden], .login[hidden], .pending[hidden], [hidden] { display: none !important; }\n.login-modal { position: fixed; inset: 0; z-index: 2147483647; background: var(--overlay); display: grid; place-items: center; }\n/* shadcn/ui's dialog: a larger title, a muted description, then the login link and its button. */\n.panel.modal { position: static; width: min(440px, calc(100vw - 32px)); display: flex; flex-direction: column; gap: 16px; padding: 24px; border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); }\n.modal > .title { font-size: 18px; line-height: 1.2; letter-spacing: -0.01em; }\n.modal > p.message.info { padding: 0; border: 0; background: none; color: var(--muted-foreground); margin-top: -8px; }\n.pending { color: var(--warning); border-color: color-mix(in oklab, var(--warning) 40%, transparent); background: color-mix(in oklab, var(--warning) 10%, var(--background)); }\n.rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }\n.row.problem { color: var(--destructive); }\n.simple-form { display: flex; flex-direction: column; gap: 10px; }\n/* Values shown read-only, such as both sides of a conflict: line breaks kept, long lines wrapped, and a long value\n scrolls in its box rather than running past the panel or the window. */\n.snippet { font: var(--text-xs)/1.45 var(--font-mono); background: var(--muted); border-radius: var(--radius-sm); padding: 6px 8px; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 14em; overflow: auto; margin: 0; }\n/* shadcn/ui's dropdown menu (src/ui/menu.ts). */\n.menu {\n position: fixed; z-index: 2147483647; display: flex; flex-direction: column; padding: 4px;\n background: var(--popover); color: var(--popover-foreground);\n border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-md);\n animation: baack-fade-in 100ms ease-out;\n}\n.menu-item {\n justify-content: flex-start; gap: 8px; width: 100%; min-height: 0; padding: 6px 8px;\n border: 0; border-radius: var(--radius-sm); background: none; font-weight: 400; white-space: nowrap;\n}\n.menu-item svg { color: var(--muted-foreground); }\n.menu-item:enabled:hover, .menu-item:focus-visible { background: var(--accent); color: var(--accent-foreground); box-shadow: none; }\n.menu-item:active { transform: none; }\n.menu-item.destructive { color: var(--destructive-text); }\n.menu-item.destructive svg { color: currentColor; }\n/* shadcn/ui's tooltip (src/ui/tooltip.ts). */\n.tooltip {\n position: fixed; z-index: 2147483647; pointer-events: none; max-width: 280px; width: max-content;\n padding: 6px 12px; border-radius: var(--radius-md); background: var(--foreground); color: var(--background);\n font: var(--text-xs)/1.35 var(--font-sans); animation: baack-fade-in 100ms ease-out;\n}\n@keyframes baack-fade-in { from { opacity: 0; transform: scale(0.96); } }\n@media (prefers-reduced-motion: reduce) { .menu, .tooltip { animation: none; } }\n/* The sidebar (src/ui/stack.ts), docked right (or left); a bottom sheet on narrow screens. */\n.side { top: 16px; right: 16px; bottom: 16px; width: min(420px, calc(100vw - 32px)); display: flex; flex-direction: column; gap: 8px; padding: 12px 14px; box-shadow: var(--shadow-lg); }\n.side[data-side=\"left\"] { right: auto; left: 16px; }\n/* shadcn/ui's sheet, floating clear of the page's edge: it slides in from its side, or up from the bottom. */\n.side.stack:not([hidden]) { animation: baack-sheet-right 200ms ease-out; }\n.side.stack[data-side=\"left\"]:not([hidden]) { animation-name: baack-sheet-left; }\n@keyframes baack-sheet-right { from { transform: translateX(calc(100% + 16px)); } }\n@keyframes baack-sheet-left { from { transform: translateX(calc(-100% - 16px)); } }\n@keyframes baack-sheet-up { from { transform: translateY(calc(100% + 16px)); } }\n@media (prefers-reduced-motion: reduce) { .side.stack:not([hidden]) { animation: none !important; } }\n.side-dock { white-space: nowrap; }\n@media (max-width: 640px) {\n .side.stack, .side.stack[data-side=\"left\"] { top: auto; left: 8px; right: 8px; width: auto; max-height: 60vh; border-radius: var(--radius-xl) var(--radius-xl) var(--radius-md) var(--radius-md); }\n .side.stack.item-editing { display: none; }\n /* A sheet has no side to dock on. */\n .side.stack .side-dock { display: none; }\n .side.stack:not([hidden]), .side.stack[data-side=\"left\"]:not([hidden]) { animation-name: baack-sheet-up; }\n /* The sheet's grip, as on a drawer. */\n .side.stack::before { content: \"\"; align-self: center; flex-shrink: 0; width: 40px; height: 4px; margin: -4px 0 2px; border-radius: 999px; background: var(--muted-foreground); opacity: 0.35; }\n}\n/* The sidebar stack (src/ui/stack.ts): Back, breadcrumb, title, then the level on screen. */\n.stack { gap: 4px; }\n/* The toolbar's entity: its title, then its state and unsaved count, as one line of text that wraps. */\n.entity-label { display: block; width: 100%; padding: 6px 10px; text-align: left; font-weight: 400; line-height: 1.4; }\n.level-lifecycle { display: flex; flex-direction: column; gap: 6px; margin-bottom: 6px; }\n.level-entity, .level-slots, .level-page { display: flex; flex-direction: column; gap: 8px; }\n.stack-bar { display: flex; align-items: center; gap: 6px; }\n.stack-spacer { flex: 1 1 auto; }\n.stack-back { max-width: 60%; padding-left: 4px; }\n.stack-back-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.stack-close { white-space: nowrap; }\n.stack-crumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; list-style: none; margin: 0; padding: 0; font-size: var(--text-xs); color: var(--muted-foreground); overflow-wrap: anywhere; }\n.stack-crumbs li { display: inline-flex; align-items: center; }\n.stack-crumb-separator svg { width: 14px; height: 14px; }\n.stack-crumb { border: none; background: none; min-height: 0; padding: 0; font-size: inherit; font-weight: 400; color: var(--muted-foreground); }\n.stack-crumb:hover { background: none; color: var(--foreground); }\n.stack-crumb:active { transform: none; }\n.stack-crumbs [aria-current=\"page\"] { color: var(--foreground); }\n.stack-title { margin: 0; font-size: var(--text-base); font-weight: 600; outline: none; }\n.stack-body { position: relative; flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; border-top: 1px solid var(--border); padding-top: 8px; }\n.stack-level.leaving { position: absolute; left: 0; right: 0; background: var(--popover); z-index: 1; }\n.stack-row { display: flex; justify-content: flex-start; align-items: center; gap: 8px; width: 100%; text-align: left; margin: 0 0 4px; padding: 8px 10px; background: var(--popover); box-shadow: none; }\n.stack-row-text { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }\n.stack-row-label { font-weight: 600; }\n.stack-chevron { display: inline-flex; color: var(--muted-foreground); }\n.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; margin: 0; padding: 0; }\n.tab-panel { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 8px; }\n.tab-panel > .outline-body { flex: 1 1 auto; min-height: 0; }\n.outline-header { display: flex; justify-content: space-between; align-items: center; }\n.outline-body { overflow: auto; display: flex; flex-direction: column; gap: 14px; }\n.section-title { margin: 0; font-size: var(--text-sm); }\n.outline-group { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }\n.group-heading { display: flex; justify-content: space-between; align-items: center; color: var(--foreground); font-size: var(--text-xs); font-weight: 600; border-bottom: 1px solid var(--border); padding-bottom: 4px; }\n.group-hint { margin: 0; color: var(--muted-foreground); font-size: var(--text-xs); }\n.section-status { margin: 2px 0 0; color: var(--muted-foreground); font-size: var(--text-xs); }\n.status.note { background: var(--secondary); color: var(--secondary-foreground); }\n.outline .row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; padding: 3px 0; border-bottom: 1px solid var(--border); }\n.row-main { flex: 1 1 auto; display: flex; flex-wrap: wrap; justify-content: flex-start; align-items: baseline; gap: 4px; text-align: left; border: 0; background: none; padding: 2px 6px; font-weight: 400; }\nbutton.row-main { min-height: 0; }\nbutton.row-main:hover { background: var(--accent); }\nbutton.row-main:active, .stack-row:active { transform: none; }\n.row-name { font-weight: 600; }\n.row-name.link { font-weight: 600; }\n.outline .row.current { background: color-mix(in oklab, var(--primary) 8%, var(--popover)); box-shadow: inset 3px 0 0 var(--primary); }\n/* Tasks (milestone 13): mini cards with space between them, a task's level in sections. */\n.task-list { list-style: none; margin: 8px 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }\n.task-card {\n display: flex; justify-content: flex-start; align-items: center; gap: 8px; width: 100%; min-height: 0; height: auto;\n padding: 10px 12px; text-align: left; white-space: normal; font-weight: 400;\n background: var(--popover); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);\n}\n.task-card:hover { background: var(--accent); border-color: var(--input); }\n.task-card:active { transform: none; }\n.task-card-text { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }\n.task-title { font-weight: 600; color: var(--foreground); }\n.task-facts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: var(--text-xs); }\n.task-assignee { display: inline-flex; align-items: center; gap: 4px; }\n.avatar { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex-shrink: 0; border-radius: 999px; font: 600 10px/1 var(--font-sans); }\n.avatar-0 { background: color-mix(in oklab, var(--primary) 16%, var(--popover)); color: var(--primary); }\n.avatar-1 { background: color-mix(in oklab, var(--success) 16%, var(--popover)); color: var(--success); }\n.avatar-2 { background: color-mix(in oklab, var(--warning) 16%, var(--popover)); color: var(--warning); }\n.avatar-3 { background: color-mix(in oklab, var(--preview) 16%, var(--popover)); color: var(--preview); }\n.avatar-4 { background: color-mix(in oklab, var(--destructive) 14%, var(--popover)); color: var(--destructive-text); }\n.avatar-5 { background: var(--secondary); color: var(--secondary-foreground); }\n.task-status.tone-active { background: color-mix(in oklab, var(--primary) 12%, var(--popover)); color: var(--primary); }\n.task-status.tone-danger { background: color-mix(in oklab, var(--destructive) 10%, var(--popover)); color: var(--destructive-text); }\n.task-status.tone-success { background: transparent; border-color: var(--success); color: var(--success); }\n.task-status.tone-muted { color: var(--muted-foreground); }\n.level-tasks > .actions { margin-top: 4px; }\n.level-task { display: flex; flex-direction: column; gap: 14px; }\n.task-description { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }\n.task-section { display: flex; flex-direction: column; gap: 6px; }\n.task-activity { list-style: none; margin: 0; padding: 0; }\n.task-entry { padding: 6px 0; border-bottom: 1px solid var(--border); }\n.task-entry-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; font-size: var(--text-xs); }\n.task-comment { margin: 4px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }\n/* Badges: shadcn/ui's badge, for lifecycle and item states. Secondary unless the state says otherwise. */\n.status, .flag {\n display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0; white-space: nowrap;\n height: 20px; padding: 0 8px; border-radius: 999px; border: 1px solid transparent;\n font: 500 var(--text-xs)/1 var(--font-sans); background: var(--secondary); color: var(--secondary-foreground);\n}\n.status-unpublished-changes, .status-unsaved { background: color-mix(in oklab, var(--warning) 12%, var(--popover)); color: var(--warning); }\n.status-not-in-content, .flag { background: color-mix(in oklab, var(--destructive) 10%, var(--popover)); color: var(--destructive-text); }\n.status-up-to-date { background: transparent; border-color: var(--success); color: var(--success); }\n.history-row { flex-direction: column; align-items: stretch !important; gap: 4px !important; padding: 8px 0 !important; }\n.history-row > .actions { margin-top: -2px; }\n.history-row > .row-main { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; width: 100%; text-align: left; }\n.history-row > .row-main .stack-chevron { margin-left: auto; }\n.version-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 0 0 8px; }\n.version-change { margin-bottom: 8px; }\n.level-confirm .description { margin: 8px 0; }\n.level-confirm > .meta { margin-top: 0; }\n/* A long review keeps Publish in reach: its buttons stay at the bottom of the sidebar. */\n.level-review > .actions { position: sticky; bottom: 0; background: var(--popover); padding: 8px 0 2px; border-top: 1px solid var(--border); }\n.level-schedule { display: flex; flex-direction: column; gap: 8px; }\n.level-schedule .hint { margin: 0; }\n.row > .change { padding-inline: 6px; }\n.change { white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--text-xs); color: var(--foreground); }\n.change ins { background: color-mix(in oklab, var(--success) 15%, transparent); color: var(--success); text-decoration: underline; }\n.change del { background: color-mix(in oklab, var(--destructive) 12%, transparent); color: var(--destructive); }\n.change .delta { font-weight: 600; padding: 0 3px; border-radius: 3px; }\n/* The arrow glyph sits low in most fonts: centre it on the line. */\n.change .arrow { display: inline-block; vertical-align: middle; line-height: 1; margin: 0 0.35em; }\n.change .delta.up { background: color-mix(in oklab, var(--success) 15%, transparent); color: var(--success); }\n.change .delta.down { background: color-mix(in oklab, var(--destructive) 12%, transparent); color: var(--destructive); }\n.slot-preview { display: flex; align-items: center; gap: 6px; }\n.slot-preview img { width: 56px; height: 40px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--border); }\n.slot-preview .meta { font-size: 11px; overflow-wrap: anywhere; }\n.extras:empty { display: none; }\n.extras { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 4px; }\n.extras button { white-space: nowrap; }\n.popover .title { overflow-wrap: anywhere; }\n.reorder-row { align-items: center; }\n.reorder-row.dragging { opacity: 0.5; }\n.handle { display: inline-flex; cursor: grab; color: var(--muted-foreground); padding: 0 2px; }\n.entities:empty { display: none; }\n.entities { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--border); padding-top: 6px; max-height: 50vh; overflow: auto; }\n.entity { display: flex; flex-direction: column; gap: 4px; }\n.entity + .entity { border-top: 1px dashed var(--border); padding-top: 6px; }\n.unsent { color: var(--warning); }\n.lifecycle-status { font-weight: 600; color: var(--foreground); }\n.title { font-weight: 600; }\n.meta { color: var(--muted-foreground); font-weight: 400; }\n/* Buttons wrap whole onto the next line rather than squeezing their labels. */\n.actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }\n.actions > button { white-space: nowrap; }\n.hint { margin: 0; color: var(--muted-foreground); font-size: var(--text-xs); }\n`;\n\nexport interface EditorHost {\n readonly element: HTMLElement;\n readonly root: ShadowRoot;\n}\n\n/** Creates the host, or returns the existing one if the loader ran twice. */\nexport function createHost(): EditorHost {\n let element = document.getElementById(HOST_ID);\n if (!element) {\n element = document.createElement('div');\n element.id = HOST_ID;\n element.attachShadow({ mode: 'open' });\n document.body.append(element);\n }\n const root = element.shadowRoot!;\n if (!root.querySelector('style')) {\n const style = document.createElement('style');\n style.textContent = STYLES;\n root.append(style);\n }\n return { element, root };\n}\n\n/**\n * A collapsed \"Debug\" section showing an API error body (pretty-printed JSON),\n * inserted as text. Empty when there is nothing to show.\n */\nexport function debugDetails(debug: string | undefined): HTMLElement[] {\n if (!debug) return [];\n const details = el('details', 'debug');\n details.append(el('summary', '', 'Debug'), el('pre', '', debug));\n return [details];\n}\n\n/** shadcn/ui's button variants. Outline is the editor's usual button, so it has no class. */\nexport type ButtonVariant = 'primary' | 'outline' | 'secondary' | 'ghost' | 'destructive' | 'link';\nexport type ButtonSize = 'xs' | 'sm' | 'default' | 'lg' | 'icon' | 'icon-sm' | 'icon-xs';\n\n/** A button (type \"button\", so it never submits a form) with its label as text. */\nexport function button(label: string, variant: ButtonVariant = 'outline', size: ButtonSize = 'default', className = ''): HTMLButtonElement {\n const classes = [className, variant === 'outline' ? '' : variant, size === 'default' ? '' : size].filter(Boolean).join(' ');\n const element = el('button', classes, label);\n element.type = 'button';\n return element;\n}\n\n/** The variant for an action that may be marked primary or destructive. */\nexport function variantOf(action: { primary?: boolean; destructive?: boolean }): ButtonVariant {\n return action.destructive ? 'destructive' : action.primary ? 'primary' : 'outline';\n}\n\n/** A select with shadcn/ui's chevron in place of the browser's arrow. */\nexport function selectBox(select: HTMLSelectElement): HTMLElement {\n const box = el('span', 'select-box');\n box.append(select, icon('chevron-down'));\n return box;\n}\n\n/** Creates an element with a class and optional text, as text. */\nexport function el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className = '',\n text = '',\n): HTMLElementTagNameMap[K] {\n const element = document.createElement(tag);\n if (className) element.className = className;\n if (text) element.textContent = text;\n return element;\n}\n", "// The only UI the loader needs: the button that loads the editor. Kept apart\n// from the toolbar so anonymous visitors never download the rest.\n\nimport { el, type EditorHost } from './host.ts';\n\nexport const EDIT_LABEL = 'Edit page';\n\n/** The loader's minimal toolbar: just the button that loads the editor. */\nexport function createLauncher(host: EditorHost): HTMLButtonElement {\n const existing = host.root.querySelector<HTMLButtonElement>('.toolbar button.mode');\n if (existing) return existing;\n const bar = el('div', 'panel toolbar');\n bar.setAttribute('role', 'region');\n bar.setAttribute('aria-label', 'Baack editor');\n const row = el('div', 'toolbar-row');\n const button = el('button', 'mode', EDIT_LABEL);\n button.type = 'button';\n button.setAttribute('aria-pressed', 'false');\n row.append(el('span', 'brand', 'Baack'), button);\n bar.append(row);\n host.root.append(bar);\n return button;\n}\n", "// Baack's login in a window of its own rather than a frame: an API that doesn't list a site in its frame-ancestors\n// refuses the frame, and some browsers (mobile Chrome among them) wouldn't show it. A link that opens a popup window,\n// or a new tab where popups are blocked; once the session starts, the editor closes the window it opened.\n\nimport { el } from './host.ts';\n\nconst NAME = 'baack-login';\nconst FEATURES = 'popup,width=480,height=640';\n\nexport interface LoginLink {\n element: HTMLAnchorElement;\n /** Closes the login window, if this link opened it and it's still open. */\n close(): void;\n}\n\n/**\n * A link to Baack's login, styled as a primary button. It opens the login in a popup window from the click, so popup\n * blockers allow it; if one is blocked anyway, the link opens it in a new tab.\n */\nexport function loginLink(src: string, label = 'Log in to Baack'): LoginLink {\n const element = el('a', 'button primary', label);\n element.href = src;\n element.target = NAME;\n let popup: Window | null = null;\n element.addEventListener('click', (event) => {\n popup = window.open(src, NAME, FEATURES);\n if (popup) {\n event.preventDefault();\n popup.focus();\n }\n });\n return {\n element,\n close: () => {\n if (popup && !popup.closed) popup.close();\n popup = null;\n },\n };\n}\n\n/** Calls `check` when the page is back in front, as after logging in in another window or tab. Returns a stop. */\nexport function whenBack(check: () => void): () => void {\n const onVisible = () => {\n if (document.visibilityState === 'visible') check();\n };\n window.addEventListener('focus', check);\n document.addEventListener('visibilitychange', onVisible);\n return () => {\n window.removeEventListener('focus', check);\n document.removeEventListener('visibilitychange', onVisible);\n };\n}\n", "import { Endpoint } from './endpoints.ts';\nimport { BaackApiError } from './errors.ts';\nimport type { Search } from './types/index.ts';\n\nexport interface BaackConfig {\n baseUrl: string;\n headers?: Record<string, string>;\n /**\n * Whether the browser sends cookies with each request. Use 'include' for a\n * browser client that relies on the user's Baack session from another\n * origin. Defaults to the fetch default ('same-origin').\n */\n credentials?: 'omit' | 'same-origin' | 'include';\n /**\n * Stops a failed request being sent again and again, for example by a caller that retries on every render. On by\n * default; `false` turns it off.\n *\n * - An invalid request (`BaackApiError.isInvalidRequest`: a 400 such as a missing required field) is permanent: the\n * same request isn't sent again for `refusedHoldMs`, and fails at once with the same error.\n * - After any other failure (another 4xx such as an expired session, a server error, a timeout, a rate limit or a\n * network failure) the same request waits `backoffMs`, doubling with each failure in a row up to `maxBackoffMs`,\n * plus up to a fifth more at random so many clients don't all try again together, and fails at once with the last\n * error until then. A longer `Retry-After` from the API is honoured.\n *\n * The same request means the same method, URL, body and per-request headers. A different request is always sent,\n * and a success clears the request's record. Uploads (`upload`) aren't guarded. The client doesn't retry by itself.\n * A held `BaackApiError` says until when in `heldUntil`.\n */\n failureGuard?: FailureGuard | false;\n}\n\nexport interface FailureGuard {\n /** How long an invalid request isn't sent again unchanged. Default 5 minutes. */\n refusedHoldMs?: number;\n /** The wait after the first failure that may pass. Default 1 second. */\n backoffMs?: number;\n /** The longest wait. Default 1 minute. */\n maxBackoffMs?: number;\n}\n\nconst GUARD_DEFAULTS: Required<FailureGuard> = { refusedHoldMs: 300_000, backoffMs: 1_000, maxBackoffMs: 60_000 };\n\n/** The most failed requests a client remembers; the oldest is forgotten first. */\nconst MAX_REMEMBERED_FAILURES = 500;\n\n/** The most a backoff wait is lengthened at random, as a fraction of it. */\nconst BACKOFF_JITTER = 0.2;\n\ninterface FailedRequest {\n error: unknown;\n /** No request before this time (ms since the epoch). */\n until: number;\n /** Failures in a row. */\n failures: number;\n}\n\n/**\n * The HTTP method behind each of the API's operations, named as the API docs\n * and this client's methods name them: `Method.UPDATE` is `PUT`. Use these\n * rather than HTTP method strings, for example in tests or a proxy allowlist.\n */\nexport const Method = {\n CREATE: 'POST',\n READ: 'GET',\n UPDATE: 'PUT',\n DELETE: 'DELETE',\n} as const;\nexport type Method = (typeof Method)[keyof typeof Method];\n\nexport type QueryParams =Record<string, string | number | boolean | null | undefined>;\n\nexport class BaackClient {\n private baseUrl: string;\n private defaultHeaders: Record<string, string>;\n private credentials: BaackConfig['credentials'];\n private guard: Required<FailureGuard> | undefined;\n /** Recently failed requests, by method, URL, body and per-request headers. */\n private failed = new Map<string, FailedRequest>();\n\n constructor(config: BaackConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.defaultHeaders = { ...config.headers };\n this.credentials = config.credentials;\n this.guard = config.failureGuard === false ? undefined : { ...GUARD_DEFAULTS, ...config.failureGuard };\n }\n\n /**\n * Core request handler.\n * Supports both Browser and Node environments via global fetch.\n *\n * Throws BaackApiError for any non-2xx response. Resolves to undefined for\n * an empty response body (for example a 204 from a delete).\n */\n private async request<T>(\n path: string,\n options: RequestInit = {},\n params?: QueryParams\n ): Promise<T> {\n const url = new URL(this.baseUrl + path);\n if (params) {\n Object.entries(params).forEach(([k, v]) => {\n if (v !== undefined && v !== null) {\n url.searchParams.append(k, String(v));\n }\n });\n }\n\n // Only declare a JSON body when there is one: a Content-Type header on a\n // bodiless cross-origin GET forces a CORS preflight.\n const headers: Record<string, string> = typeof options.body === 'string'\n ? { 'Content-Type': 'application/json', ...this.defaultHeaders }\n : { ...this.defaultHeaders };\n\n const init: RequestInit = {\n ...options,\n headers: {\n ...headers,\n ...(options.headers as Record<string, string> | undefined),\n },\n };\n if (this.credentials) {\n init.credentials = this.credentials;\n }\n\n const method = options.method ?? Method.READ;\n const sent = typeof init.body === 'string' ? init.body : undefined;\n // A multipart body (an upload) can't be told apart cheaply, so uploads aren't guarded.\n const key = init.body === undefined || sent !== undefined\n ? `${method} ${url.toString()} ${sent ?? ''} ${headerKey(options.headers)}`\n : undefined;\n const held = this.guard && key !== undefined && this.failed.get(key);\n if (held && Date.now() < held.until) throw held.error;\n\n let response: Response;\n try {\n response = await fetch(url.toString(), init);\n } catch (error) {\n // A network failure (fetch rejects with a TypeError): transient, so back off.\n this.recordFailure(key, error, false);\n throw error;\n }\n const text = await response.text();\n\n if (!response.ok) {\n const retryAfterMs = parseRetryAfter(response.headers.get('Retry-After'));\n const error = new BaackApiError(response.status, response.statusText, text, method, url.toString(), sent, retryAfterMs);\n this.recordFailure(key, error, error.isInvalidRequest);\n throw error;\n }\n\n if (key !== undefined) this.failed.delete(key);\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n /** Remembers a failed request, so the guard can hold back the same request (see `BaackConfig.failureGuard`). */\n private recordFailure(key: string | undefined, error: unknown, invalid: boolean): void {\n if (!this.guard || key === undefined) return;\n const failures = (this.failed.get(key)?.failures ?? 0) + 1;\n const backoff = Math.min(this.guard.backoffMs * 2 ** (failures - 1), this.guard.maxBackoffMs);\n const retryAfterMs = error instanceof BaackApiError ? error.retryAfterMs ?? 0 : 0;\n const wait = Math.max(\n invalid ? this.guard.refusedHoldMs : backoff * (1 + Math.random() * BACKOFF_JITTER),\n retryAfterMs,\n );\n const until = Date.now() + wait;\n if (error instanceof BaackApiError) error.heldUntil = until;\n this.failed.delete(key);\n this.failed.set(key, { error, until, failures });\n if (this.failed.size > MAX_REMEMBERED_FAILURES) this.failed.delete(this.failed.keys().next().value!);\n }\n\n /**\n * CREATE / POST method for creating resources. `headers` are added to this request only, e.g. a CSRF header.\n */\n public async create<T>(endpoint: string, body?: unknown, headers?: Record<string, string>): Promise<T> {\n return this.request<T>(endpoint, jsonInit(Method.CREATE, body, headers));\n }\n\n /**\n * READ / GET method for all endpoints. `headers` are added to this request\n * only: a server reading the entity view for a visitor can forward their\n * `Accept-Language`, so the view picks the best available language.\n */\n public async read<T>(endpoint: string, urn: string, params?: QueryParams, headers?: Record<string, string>): Promise<T> {\n return this.request<T>(join(endpoint, urn), { method: Method.READ, ...(headers ? { headers } : {}) }, params);\n }\n\n /**\n * UPDATE / PUT for updating representations. `headers` are added to this request only.\n */\n public async update<T>(endpoint: string, urn: string, body?: unknown, headers?: Record<string, string>): Promise<T> {\n return this.request<T>(join(endpoint, urn), jsonInit(Method.UPDATE, body, headers));\n }\n\n /**\n * DELETE for deleting representations\n */\n public async delete<T = undefined>(endpoint: string, urn: string, headers?: Record<string, string>): Promise<T> {\n return this.request<T>(join(endpoint, urn), {\n method: Method.DELETE,\n ...(headers ? { headers } : {}),\n });\n }\n\n /**\n * POST a multipart form, for example an image file upload. The browser sets\n * the multipart Content-Type and boundary itself.\n */\n public async upload<T>(endpoint: string, form: FormData): Promise<T> {\n return this.request<T>(endpoint, { method: Method.CREATE, body: form });\n }\n\n /**\n * POST a urlencoded form, such as the account setup form, asking for JSON back. The fields go in the request body,\n * never the URL. `headers` are added to this request only. A refused form answers with an `ApiError` whose\n * `fields` name the fields at fault.\n */\n public async submitForm<T>(endpoint: string, form: URLSearchParams, headers?: Record<string, string>): Promise<T> {\n return this.request<T>(endpoint, {\n method: Method.CREATE,\n body: form.toString(),\n headers: { 'Content-Type': 'application/x-www-form-urlencoded', ...headers },\n });\n }\n\n /**\n * Starts a search (`owner`, `includeScopes`, optional `order`). The result\n * may be partial (`status` before `FULL_RESULT`): read it again with\n * `searchResult` until it is full, and follow its `pagination`.\n */\n public async search(params: Search): Promise<Search> {\n return this.create<Search>(Endpoint.SEARCH, params);\n }\n\n /** Reads a search's results again by its URN, optionally from a page (`after`). */\n public async searchResult(urn: string, after?: string): Promise<Search> {\n return this.read<Search>(Endpoint.SEARCH, urn, { after });\n }\n}\n\n/**\n * Appends a URN or path to an endpoint. Endpoints end with a slash and paths\n * such as '/home' start with one, so drop the duplicate: the API accepts\n * either, but one slash is the canonical URL.\n */\nfunction join(endpoint: string, urn: string): string {\n return endpoint.endsWith('/') && urn.startsWith('/') ? endpoint + urn.slice(1) : endpoint + urn;\n}\n\n/** The per-request headers as part of the guard's key, in a stable order. */\nfunction headerKey(headers: RequestInit['headers']): string {\n if (!headers) return '';\n return JSON.stringify(Object.entries(headers as Record<string, string>).sort(([a], [b]) => a.localeCompare(b)));\n}\n\n/**\n * Reads a `Retry-After` header, given in seconds or as an HTTP date, as milliseconds from now. Undefined when there is\n * no header or it can't be read.\n */\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (header === null || header.trim() === '') return undefined;\n const seconds = Number(header);\n if (Number.isFinite(seconds)) return seconds >= 0 ? seconds * 1000 : undefined;\n const date = Date.parse(header);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n}\n\nfunction jsonInit(method: Method, body: unknown, headers?: Record<string, string>): RequestInit {\n const init: RequestInit = body === undefined ? { method } : { method, body: JSON.stringify(body) };\n return headers ? { ...init, headers } : init;\n}\n"],
|
|
5
|
+
"mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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",
|
|
6
|
+
"names": ["readConfig", "meta", "path", "d", "dot", "cx", "cy", "ICONS", "SVG", "icon", "name", "svg", "attribute", "value", "tag", "attributes", "shape", "LIGHT", "DARK", "SCALE", "tokens", "set", "name", "value", "THEME_CSS", "PAGE_COLOURS", "HOST_ID", "STYLES", "THEME_CSS", "createHost", "element", "root", "style", "debugDetails", "debug", "details", "el", "button", "label", "variant", "size", "className", "classes", "variantOf", "action", "selectBox", "select", "box", "icon", "tag", "text", "EDIT_LABEL", "createLauncher", "host", "existing", "bar", "el", "row", "button", "NAME", "FEATURES", "loginLink", "src", "label", "element", "el", "popup", "event", "whenBack", "check", "onVisible", "GUARD_DEFAULTS", "MAX_REMEMBERED_FAILURES", "BACKOFF_JITTER", "Method", "BaackClient", "config", "path", "options", "params", "url", "k", "v", "headers", "init", "method", "sent", "key", "headerKey", "held", "response", "error", "text", "retryAfterMs", "parseRetryAfter", "BaackApiError", "invalid", "failures", "backoff", "wait", "until", "endpoint", "body", "jsonInit", "urn", "join", "form", "Endpoint", "after", "a", "b", "header", "seconds", "date"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as T,c as R}from"./chunk-5RFN34CS.js";var h=["blockedBy","blocking","associatedTasks","associatedEntities","associatedIdentities","associatedCompanies"];function d(t){return typeof t=="string"?t:t.urn}function p(t){return{urn:d(t)}}function l(t){let e=new Set,n=[];for(let o of t??[]){let r=d(o);e.has(r)||(e.add(r),n.push({urn:r}))}return n}function D(t,e){return t==null||e==null?t==null&&e==null:d(t)===d(e)}function x(t,e){let n=new Set((t??[]).map(d)),o=new Set((e??[]).map(d));return n.size===o.size&&[...n].every(r=>o.has(r))}function F(t,e){return l([...t??[],e])}function W(t,e){let n=d(e);return l(t).filter(o=>o.urn!==n)}var pe=/(?:Z|[+-]\d{2}:?\d{2})$/i;function m(t){if(!t)return;let e=new Date(pe.test(t)?t:t+"Z");return Number.isNaN(e.getTime())?void 0:e}function me(t){return t.toISOString().replace(/Z$/,"")}function ke(t){let e=m(t);if(!e)return"";let n=o=>String(o).padStart(2,"0");return`${e.getFullYear()}-${n(e.getMonth()+1)}-${n(e.getDate())}T${n(e.getHours())}:${n(e.getMinutes())}`}function Ke(t){if(!t)return;let e=new Date(t);return Number.isNaN(e.getTime())?void 0:me(e)}var L=["UNDEFINED","PENDING","IN_PROGRESS","BLOCKED","COMPLETED","CLOSED"],b=["NONE","LOW","MEDIUM","HIGH","CRITICAL"],Y={UNDEFINED:"Undefined",PENDING:"Pending",IN_PROGRESS:"In progress",BLOCKED:"Blocked",COMPLETED:"Completed",CLOSED:"Closed"},G={NONE:"None",LOW:"Low",MEDIUM:"Medium",HIGH:"High",CRITICAL:"Critical"},Te=new Set(["COMPLETED","CLOSED"]);function ge(t){return t!=null&&Te.has(t)}function g(t){return!ge(t.status)}function _(t){return m(t.dueTimestamp)}function k(t,e=new Date){let n=_(t);return g(t)&&n!==void 0&&n.getTime()<e.getTime()}function Ue(t,e,n=new Date){let o=_(t);if(!g(t)||o===void 0)return!1;let r=o.getTime()-n.getTime();return r>=0&&r<=e}var j=(t,e)=>b.indexOf(e.priority)-b.indexOf(t.priority),ve=(t,e)=>L.indexOf(t.status)-L.indexOf(e.status),$=(t,e)=>{let[n,o]=[I(t.dueTimestamp),I(e.dueTimestamp)];return n===o?0:n-o},Fe=(t,e)=>-(I(t.updatedTimestamp,0)-I(e.updatedTimestamp,0)),H=(t,e)=>t.title.localeCompare(e.title);function V(...t){return(e,n)=>{for(let o of t){let r=o(e,n);if(r!==0)return r}return 0}}var J=(t,e)=>Number(g(e))-Number(g(t)),We=V(J,$,j,H),Ye=V(J,j,$,H);function I(t,e=Number.POSITIVE_INFINITY){return m(t)?.getTime()??e}function he(t,e,n=new Date){if(e.status&&!e.status.includes(t.status)||e.priority&&!e.priority.includes(t.priority)||e.assignee&&!C(t.assignee,e.assignee)||e.project&&!C(t.project,e.project)||e.workflowStage&&!C(t.workflowStage,e.workflowStage)||e.relatedTo!==void 0&&!Ee(t,e.relatedTo)||e.open!==void 0&&g(t)!==e.open||e.overdue&&!k(t,n))return!1;if(e.text){let o=e.text.toLocaleLowerCase();if(!`${t.title}
|
|
2
|
+
${t.description}`.toLocaleLowerCase().includes(o))return!1}return!0}function Ge(t,e,n=new Date){return t.filter(o=>he(o,e,n))}function Ee(t,e){let n=d(e);return[t.blockedBy,t.blocking,t.associatedTasks,t.associatedEntities,t.associatedIdentities,t.associatedCompanies].some(r=>r?.some(s=>s.urn===n))}function C(t,e){return e.some(n=>n===null?t==null:t?.urn===d(n))}var E="";function je(t,e){let n=new Map;e==="status"&&L.forEach(o=>n.set(o,[])),e==="priority"&&[...b].reverse().forEach(o=>n.set(o,[]));for(let o of t){let r=ye(o,e),s=n.get(r);s?s.push(o):n.set(r,[o])}return n}function Se(t){return[...t.stages??[]].sort((e,n)=>(e.order??0)-(n.order??0))}function $e(t,e){let n=new Map(Se(e).map(r=>[r.urn,[]])),o=[];for(let r of t)(n.get(r.workflowStage?.urn??E)??o).push(r);return o.length>0&&n.set(E,o),n}function we(t,e){let n=t.workflowStage?.urn;return n?e.find(o=>o.stages?.some(r=>r.urn===n)):void 0}function He(t,e){let n=new Map(e.map(r=>[r.urn,[]])),o=[];for(let r of t)(n.get(we(r,e)?.urn??E)??o).push(r);return o.length>0&&n.set(E,o),n}function ye(t,e){switch(e){case"status":return t.status;case"priority":return t.priority;case"assignee":return t.assignee?.urn??E;case"project":return t.project?.urn??E;case"workflowStage":return t.workflowStage?.urn??E;case"workflow":return E}}var Z=1024,z=65536;function X(t){let{owner:e,...n}=t;return{status:"PENDING",priority:"NONE",description:"",...n,owner:p(e),blockedBy:l(n.blockedBy),blocking:l(n.blocking),associatedTasks:l(n.associatedTasks),associatedEntities:l(n.associatedEntities),associatedIdentities:l(n.associatedIdentities),associatedCompanies:l(n.associatedCompanies)}}function K(t,e={}){let n=[],{creating:o=!1,urn:r}=e;if(o&&!t.owner&&n.push({field:"owner",message:"A task needs an owning company."}),t.title!==void 0||o){let i=t.title?.trim()??"";i===""?n.push({field:"title",message:"A task needs a title."}):i.length>Z&&n.push({field:"title",message:`The title is longer than ${Z} characters.`})}t.description!==void 0&&t.description.length>z&&n.push({field:"description",message:`The description is longer than ${z} characters.`}),t.dueTimestamp!=null&&!m(t.dueTimestamp)&&n.push({field:"dueTimestamp",message:"The due date is not a valid timestamp."}),r!==void 0&&(t.blockedBy?.some(i=>i.urn===r)&&n.push({field:"blockedBy",message:"A task cannot block itself."}),t.blocking?.some(i=>i.urn===r)&&n.push({field:"blocking",message:"A task cannot block itself."}));let s=new Set((t.blockedBy??[]).map(d));return t.blocking?.some(i=>s.has(i.urn))&&n.push({field:"blocking",message:"A task cannot both block and be blocked by the same task."}),n}function Xe(t,e){let n={};for(let o of["status","priority","title","description"]){let r=e[o];r!==void 0&&r!==t[o]&&(n[o]=r)}e.dueTimestamp!==void 0&&!Oe(t.dueTimestamp,e.dueTimestamp)&&(n.dueTimestamp=e.dueTimestamp||null);for(let o of["assignee","project","workflowStage"]){let r=e[o];r!==void 0&&!D(t[o],r)&&(n[o]=r===null?null:p(r))}for(let o of h){let r=e[o];r!==void 0&&!x(t[o],r)&&(n[o]=l(r))}return n}function Qe(t,e){let n={...t};for(let o of["status","priority","title","description"])e[o]!==void 0&&(n[o]=e[o]);e.dueTimestamp!==void 0&&(n.dueTimestamp=e.dueTimestamp??"");for(let o of["assignee","project","workflowStage",...h]){let r=e[o];r!==void 0&&(n[o]=r)}return n}function Q(t,e){let n=e.owner??t.owner;if(!n)throw new TypeError(`Task ${t.urn} has no owner, which every update must send.`);let o={urn:t.urn,owner:p(n),status:e.status??t.status,priority:e.priority??t.priority,title:e.title??t.title,description:e.description??t.description??"",blockedBy:l(e.blockedBy??t.blockedBy),blocking:l(e.blocking??t.blocking),associatedTasks:l(e.associatedTasks??t.associatedTasks),associatedEntities:l(e.associatedEntities??t.associatedEntities),associatedIdentities:l(e.associatedIdentities??t.associatedIdentities),associatedCompanies:l(e.associatedCompanies??t.associatedCompanies)};for(let s of["assignee","project","workflowStage"]){let i=e[s]===void 0?t[s]:e[s];i?o[s]=p(i):e[s]===null&&(o[s]=null)}let r=e.dueTimestamp===void 0?t.dueTimestamp:e.dueTimestamp;return r?o.dueTimestamp=r:e.dueTimestamp!==void 0&&(o.dueTimestamp=null),e.identityForLogs&&(o.identityForLogs=p(e.identityForLogs)),o}function q(t){return Object.keys(t).every(e=>e==="identityForLogs")}function Oe(t,e){return m(t)?.getTime()===m(e)?.getTime()}var P=["title","description","status","priority","dueTimestamp","assignee","project","workflowStage"];function M(t,e,n){return t==="assignee"||t==="project"||t==="workflowStage"?D(e,n):t==="dueTimestamp"?m(e)?.getTime()===m(n)?.getTime():(e??"")===(n??"")}function ee(t,e){return[...P.filter(n=>!M(n,t[n],e[n])),...h.filter(n=>!x(t[n],e[n]))]}function B(t){return P.filter(e=>t[e]!==void 0)}function te(t,e,n){return B(n).filter(o=>!M(o,t[o],e[o])&&!M(o,e[o],n[o])).map(o=>({field:o,base:t[o],theirs:e[o],mine:n[o]}))}function ot(t,e){let n={...t};for(let o of P)e[o]==="theirs"&&delete n[o];return n}function ne(t,e,n){let o={...n};for(let r of h){let s=n[r];if(s===void 0)continue;let i=new Set((t[r]??[]).map(d)),u=new Set(s.map(d)),c=new Set([...i].filter(f=>!u.has(f))),a=s.filter(f=>!i.has(d(f)));o[r]=l([...(e[r]??[]).filter(f=>!c.has(d(f))),...a])}return o}function oe(t){let e=new Map;for(let n of t)e.set(n.urn,n);return n=>e.get(n)}function U(t,e){return(t.blockedBy??[]).map(n=>n.urn).filter(n=>{let o=e(n);return o===void 0||g(o)})}function at(t,e){return U(t,e).length===0}function v(t){let e=new Map,n=(o,r)=>{let s=e.get(o)??new Set;s.add(r),e.set(o,s)};for(let o of t){e.has(o.urn)||e.set(o.urn,new Set);for(let r of o.blocking??[])n(o.urn,r.urn);for(let r of o.blockedBy??[])n(r.urn,o.urn)}return e}function ut(t){let e=v(t),n=new Map,o=[],r=s=>{n.set(s,"visiting"),o.push(s);for(let i of e.get(s)??[]){let u=n.get(i);if(u==="visiting")return o.slice(o.indexOf(i));if(u===void 0){let c=r(i);if(c)return c}}o.pop(),n.set(s,"done")};for(let s of e.keys())if(n.get(s)===void 0){let i=r(s);if(i)return i}}function ct(t,e,n){let o=d(n),r=d(e);if(o===r)return!0;let s=v(t),i=[r],u=new Set(i);for(let c=i.shift();c!==void 0;c=i.shift())for(let a of s.get(c)??[]){if(a===o)return!0;u.has(a)||(u.add(a),i.push(a))}return!1}function dt(t){let e=new Set(t.map(u=>u.urn)),n=v(t),o=new Map(t.map(u=>[u.urn,0]));for(let[u,c]of n)if(e.has(u))for(let a of c)e.has(a)&&o.set(a,(o.get(a)??0)+1);let r=[],s=new Set,i=!0;for(;i;){i=!1;for(let u of t)if(!(s.has(u.urn)||o.get(u.urn)!==0)){r.push(u),s.add(u.urn),i=!0;for(let c of n.get(u.urn)??[])e.has(c)&&o.set(c,(o.get(c)??0)-1)}}return[...r,...t.filter(u=>!s.has(u.urn))]}var De={CREATED:"Created",STATUS_UNDEFINED:"Status set to Undefined",STATUS_PENDING:"Status set to Pending",STATUS_IN_PROGRESS:"Status set to In progress",STATUS_BLOCKED:"Status set to Blocked",STATUS_COMPLETED:"Status set to Completed",STATUS_COMPL_ETED:"Status set to Completed",STATUS_CLOSED:"Status set to Closed",PRIORITY_NONE:"Priority set to None",PRIORITY_LOW:"Priority set to Low",PRIORITY_MEDIUM:"Priority set to Medium",PRIORITY_HIGH:"Priority set to High",PRIORITY_CRITICAL:"Priority set to Critical",WORKFLOW_STAGE_SET:"Moved to a workflow stage",WORKFLOW_STAGE_UNSET:"Removed from its workflow stage",COMMENT_ADDED:"Commented",WORK_TASK_ASSOCIATION_ADDED:"Related task added",WORK_TASK_ASSOCIATION_REMOVED:"Related task removed",WORK_TASK_BLOCKER_ADDED:"Blocker added",WORK_TASK_BLOCKER_REMOVED:"Blocker removed",WORK_TASK_BLOCKING_ADDED:"Now blocking a task",WORK_TASK_BLOCKING_REMOVED:"No longer blocking a task",WORK_TASK_ENTITY_ADDED:"Content added",WORK_TASK_ENTITY_REMOVED:"Content removed",WORK_TASK_IDENTITY_ADDED:"Person added",WORK_TASK_IDENTITY_REMOVED:"Person removed",WORK_TASK_COMPANY_ADDED:"Company added",WORK_TASK_COMPANY_REMOVED:"Company removed",WORK_PROJECT_SET:"Added to a project",WORK_PROJECT_UNSET:"Removed from its project",ASSIGNED:"Assigned",UNASSIGNED:"Unassigned",TITLE_UPDATED:"Title changed",DESCRIPTION_UPDATED:"Description changed",DUE_DATE_UPDATED:"Due date changed",DUE_DATE_UNSET:"Due date removed"};function lt(t){return De[t]??t.toLowerCase().replaceAll("_"," ")}function xe(t){return t.activity==="COMMENT_ADDED"}function pt(t){let e=t.filter(xe),n=new Map(e.map(s=>[s.urn,s])),o=s=>{let i=new Set,u=s;for(;u.replyTo&&n.has(u.replyTo.urn)&&!i.has(u.urn);)i.add(u.urn),u=n.get(u.replyTo.urn);return u},r=new Map;for(let s of e){let i=o(s),u=r.get(i.urn)??{comment:i,replies:[]};i!==s&&u.replies.unshift(s),r.set(i.urn,u)}return[...r.values()]}var Ie={people:[],projects:[],tasks:[]};function se(t){let e=t.persons?.[0]?.names?.[0];return[e?.givenName,e?.familyName].filter(Boolean).join(" ")||void 0}function ie(t){return t.emails?.find(e=>e.email)?.email||void 0}function ht(t){let e=t.item,n=e&&typeof e=="object"?ie(e):void 0;return{urn:t.urn,name:t.name??"",...n?{email:n}:{}}}function ae(t){return se(t)||t.label?.trim()||t.emails?.[0]?.email||void 0}function re(t,e){return e.name||se(e)||t.people.find(n=>n.urn===e.urn)?.name||e.label||e.title||t.projects.find(n=>n.urn===e.urn)?.name||t.tasks.find(n=>n.urn===e.urn)?.title||t.companies?.find(n=>n.urn===e.urn)?.name||t.entities?.find(n=>n.urn===e.urn)?.name||t.workflows?.flatMap(n=>n.stages??[]).find(n=>n.urn===e.urn)?.name||`\u2026${e.urn.slice(-6)}`}function _e(t){return t.split(/\s+/).filter(Boolean).map(e=>e[0]).join("").slice(0,2).toUpperCase()}var Ae=6;function Ne(t){let e=0;for(let n of t)e=e*31+n.charCodeAt(0)|0;return Math.abs(e)%Ae}var Re={UNDEFINED:"muted",PENDING:"default",IN_PROGRESS:"active",BLOCKED:"danger",COMPLETED:"success",CLOSED:"muted"};function Et(t,{directory:e=Ie,lookup:n,now:o}={}){let r=_(t),s=t.assignee?{urn:t.assignee.urn,name:re(e,t.assignee),email:ie(t.assignee)??e.people.find(i=>i.urn===t.assignee.urn)?.email}:void 0;return{urn:t.urn,title:t.title,status:{value:t.status,label:Y[t.status],tone:Re[t.status]},priority:{value:t.priority,label:G[t.priority]},open:g(t),blockedBy:U(t,n??oe(e.tasks)).map(i=>({urn:i,name:re(e,{urn:i})})),due:r?{date:r,overdue:k(t,o)}:void 0,assignee:s&&{...s,initials:_e(s.name),colour:Ne(s.urn)}}}var O=class extends Error{issues;name="TaskValidationError";constructor(e){super(e.map(n=>n.message).join(" ")),this.issues=e}},A=class extends Error{searchUrn;timeoutMs;name="TaskSearchTimeoutError";constructor(e,n){super(`Search ${e??""} did not finish within ${n} ms`),this.searchUrn=e,this.timeoutMs=n}},N=class extends Error{conflicts;current;name="TaskConflictError";constructor(e,n){super(`Someone else changed ${e.map(o=>o.field).join(", ")} on task ${n.urn}`),this.conflicts=e,this.current=n}};var ue=class{client;constructor(e){this.client=e}async get(e){return this.client.read(T.TASK,d(e))}async getWorkflow(e){return this.client.read(T.WORKFLOW,d(e))}async create(e,n={}){let o=de(X(e),n),r=K(o,{creating:!0});if(r.length>0)throw new O(r);return this.client.create(T.TASK,o)}async update(e,n,o={}){let r=d(e),{base:s,onChangedElsewhere:i,...u}=o;return typeof n!="function"&&(ce(n,r),q(n)&&typeof e!="string"&&fe(e))?e:this.#t(r,async()=>{let c=await this.get(r),a=typeof n=="function"?n(c):n;if(typeof n=="function"&&ce(a,r),s){let f=new Set([...B(a),...h.filter(w=>a[w]!==void 0)]),y=ee(s,c).filter(w=>!f.has(w));y.length>0&&i?.(y,c);let S=te(s,c,a);if(S.length>0)throw new N(S,c);a=ne(s,c,a)}return this.client.update(T.TASK,r,de(Q(c,a),u))})}#e=new Map;#t(e,n){let o=(this.#e.get(e)??Promise.resolve()).catch(()=>{}).then(n);this.#e.set(e,o);let r=()=>{this.#e.get(e)===o&&this.#e.delete(e)};return o.then(r,r),o}async delete(e){await this.client.delete(T.TASK,d(e))}setStatus(e,n,o){return this.update(e,{status:n},o)}setPriority(e,n,o){return this.update(e,{priority:n},o)}assign(e,n,o){return this.update(e,{assignee:n===null?null:p(n)},o)}setDue(e,n,o){return this.update(e,{dueTimestamp:n},o)}setProject(e,n,o){return this.update(e,{project:n===null?null:p(n)},o)}setWorkflowStage(e,n,o){return this.update(e,{workflowStage:n===null?null:p(n)},o)}addBlocker(e,n,o){return this.addTo(e,"blockedBy",n,o)}removeBlocker(e,n,o){return this.removeFrom(e,"blockedBy",n,o)}addTo(e,n,o,r){return this.update(e,s=>({[n]:F(s[n],o)}),r)}removeFrom(e,n,o,r){return this.update(e,s=>({[n]:W(s[n],o)}),r)}async logs(e,n={}){let o=await this.client.read(T.TASK_LOGS,d(e),{after:n.after});return{logs:o?.logs??[],pagination:o?.pagination??null}}async allLogs(e,n={}){let{limit:o=Number.POSITIVE_INFINITY}=n,r=[],s;do{let i=await this.logs(e,s===void 0?{}:{after:s});r.push(...i.logs),s=i.pagination?.isMorePages?i.pagination.after??void 0:void 0}while(s!==void 0&&r.length<o);return r.slice(0,o)}async comment(e,n,o={}){let r={task:p(e),activity:"COMMENT_ADDED",comment:n};return o.actor!==void 0&&(r.identity=p(o.actor)),o.replyTo!==void 0&&(r.replyTo=p(o.replyTo)),this.client.create(T.TASK_LOG,r)}async list(e){let n=e.includeRelated===!1?["TASK"]:["TASK","IDENTITY","PROJECT"];return this.listing({owner:e.owner,scopes:n},e)}async about(e,n){let o=n.includeRelated===!1?["TASK"]:["TASK","IDENTITY"];return this.listing({owner:n.owner,scopes:o,context:{entities:[p(e)]}},n)}async listing(e,n){let{concurrency:o=6,signal:r}=n,s=await this.search(e,{...n.poll??{},...r?{signal:r}:{}}),i=s.filter(a=>a.type==="TASK"),u=await le(i,o,r,async a=>{if(a.item&&fe(a.item))return a.item;try{return await this.get(a.urn)}catch(f){if(R(f)&&f.isNotFound)return;throw f}}),c=await le(s.filter(a=>a.type==="IDENTITY"),o,r,async a=>{try{let f=await this.client.read(T.IDENTITY,a.urn);return{...a,name:ae(f)??a.name??null,item:f}}catch(f){if(R(f))return a;throw f}});return{tasks:u.filter(a=>a!==void 0),identities:c.filter(a=>a!==void 0),projects:s.filter(a=>a.type==="PROJECT")}}async search(e,n={}){let{intervalMs:o=250,maxIntervalMs:r=2e3,timeoutMs:s=3e4,signal:i}=n,u=Date.now()+s,c={owner:p(e.owner),includeScopes:e.scopes,...e.context?{context:e.context}:{}};i?.throwIfAborted();let a=await this.client.search(c),f=o;for(;a.status!=="FULL_RESULT";){if(!a.urn)throw new Error("The search API returned a search without a URN");if(Date.now()+f>u)throw new A(a.urn,s);await Ce(f,i),a=await this.client.searchResult(a.urn),f=Math.min(Math.round(f*1.5),r)}let y=[...a.items??[]],S=a.pagination;for(;S?.isMorePages&&S.after&&a.urn;){i?.throwIfAborted();let w=await this.client.searchResult(a.urn,S.after);y.push(...w.items??[]),S=w.pagination}return y}};function ce(t,e){let n=K(t,{urn:e});if(n.length>0)throw new O(n)}function de(t,e){return e.actor===void 0?t:{...t,identityForLogs:p(e.actor)}}function fe(t){return typeof t=="object"&&t!==null&&"urn"in t&&"title"in t&&"status"in t}function Ce(t,e){return new Promise((n,o)=>{if(e?.aborted)return o(e.reason);let r=setTimeout(()=>{e?.removeEventListener("abort",s),n()},t),s=()=>{clearTimeout(r),o(e?.reason)};e?.addEventListener("abort",s,{once:!0})})}async function le(t,e,n,o){let r=new Array(t.length),s=0,i=async()=>{for(;s<t.length;){n?.throwIfAborted();let u=s++;r[u]=await o(t[u])}};return await Promise.all(Array.from({length:Math.min(Math.max(1,e),t.length)},i)),r}export{h as a,d as b,p as c,l as d,D as e,x as f,F as g,W as h,m as i,me as j,ke as k,Ke as l,L as m,b as n,Y as o,G as p,ge as q,g as r,_ as s,k as t,Ue as u,j as v,ve as w,$ as x,Fe as y,H as z,V as A,J as B,We as C,Ye as D,he as E,Ge as F,Ee as G,E as H,je as I,Se as J,$e as K,we as L,He as M,Z as N,z as O,X as P,K as Q,Xe as R,Qe as S,Q as T,q as U,P as V,M as W,ee as X,B as Y,te as Z,ot as _,ne as $,oe as aa,U as ba,at as ca,v as da,ut as ea,ct as fa,dt as ga,De as ha,lt as ia,xe as ja,pt as ka,Ie as la,se as ma,ie as na,ht as oa,ae as pa,re as qa,_e as ra,Ae as sa,Ne as ta,Re as ua,Et as va,O as wa,A as xa,N as ya,ue as za};
|
|
3
|
+
//# sourceMappingURL=chunk-VNUXOULZ.js.map
|