@baack-software/baack-ts-editor 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/loader.js ADDED
@@ -0,0 +1,2 @@
1
+ import{a as v,b as s,d as C,g as f,l as o,m as L}from"./chunks/chunk-JI2V7IMH.js";var l=class{start;firstEnded;down(t,e){let n=t.x<e*.15||t.x>e*.85;this.firstEnded!==void 0&&t.time-this.firstEnded>800&&(this.firstEnded=void 0),this.start=n?void 0:t}cancel(){this.start=void 0,this.firstEnded=void 0}up(t,e){let n=this.start;if(this.start=void 0,!n)return!1;let i=t.x-n.x,d=t.y-n.y;return-i>=e*.3&&Math.abs(d)<=Math.abs(i)/2&&t.time-n.time<=600?this.firstEnded!==void 0?(this.firstEnded=void 0,!0):(this.firstEnded=t.time,!1):(this.firstEnded=void 0,!1)}};var A=500,R=10,m=class{client;constructor(t){this.client=new C({baseUrl:t,credentials:"include"})}clientContext(){return this.client.read(s.CLIENT_CONTEXT,"")}entityView(t,e={}){return this.client.read(s.ENTITY_VIEW,t,{version:e.version,language:e.language,variant:e.variant})}createEntity(t){return this.client.create(s.ENTITY,t)}async companies(){return(await this.client.read(s.COMPANIES,"")).companies??[]}async searchEntities(t){let e=await this.client.search({owner:{urn:t},includeScopes:["ENTITY"],order:"NAME"});for(let d=0;e.status!=="FULL_RESULT"&&e.urn&&d<R;d+=1)await new Promise(c=>setTimeout(c,A)),e=await this.client.searchResult(e.urn);let n=e.status==="FULL_RESULT",i=x(e);for(;n&&e.urn&&e.pagination?.isMorePages&&e.pagination.after;)e=await this.client.searchResult(e.urn,e.pagination.after),i.push(...x(e));return{urns:[...new Set(i)],complete:n}}create(t,e){return this.client.create(t.endpoint,e)}read(t,e){return this.client.read(t.endpoint,e)}update(t,e,n){return this.client.update(t.endpoint,e,n)}async remove(t,e){await this.client.delete(t.endpoint,e)}history(t,e,n){return this.client.read(t.historyEndpoint,e,{after:n})}publishVersion(t,e){return this.client.update(t.historyEndpoint,e.urn,e)}readEntity(t){return this.client.read(s.ENTITY,t)}updateEntity(t,e){return this.client.update(s.ENTITY,t,e)}createTask(t){return this.client.create(s.TASK,t)}uploadImageFile(t,e,n){let i=new FormData;return i.append("imageItemUrn",t),i.append("imageItemSize",e),i.append("src",n,n.name),this.client.upload(s.IMAGE_FILE,i)}};function x(r){return(r.items??[]).filter(t=>t.type==="ENTITY"&&t.urn).map(t=>t.urn)}var k="baack-editor:editor",b=2e3,I=new m(v().baseUrl),g=!1,E=!1;async function S(){if(window.baackEditorLoaded)return;window.baackEditorLoaded=!0;let r=new URLSearchParams(location.search),t=r.get("version"),e=t==="LATEST"?"LATEST":t&&/^\d+$/.test(t)?Number(t):void 0,n=r.has("edit")||e!==void 0;document.addEventListener("keydown",i=>{i.altKey&&i.shiftKey&&i.code==="KeyE"&&(i.preventDefault(),h(!0,e))}),N(()=>{h(!0,e)}),(n||D())&&await h(n,e)}async function h(r,t){if(g||E)return;E=!0;let e;try{e=await I.clientContext()}catch(n){console.warn("Baack editor: could not read the client context; editing is unavailable.",n);return}finally{E=!1}e.hasSession===!0?M(e,t):r&&_(e.loginIframeSrc,t)}function M(r,t){if(g)return;g=!0,F();let e=f(),n=L(e),i=async()=>{n.disabled=!0,(await import("./editor.js")).start({transport:I,host:e,context:r,...t!==void 0?{mode:t}:{}})};t!==void 0?i():n.addEventListener("click",()=>{i()},{once:!0})}function _(r,t){let e=f();if(e.root.querySelector(".login-modal"))return;let n=o("div","login-modal"),i=o("div","panel modal");i.setAttribute("role","dialog"),i.setAttribute("aria-modal","true"),i.setAttribute("aria-label","Log in to edit");let d=o("div","title",t!==void 0?"Log in to see draft content":"Log in to edit this page"),c=o("p","message info",t!==void 0?"This link shows draft content. Log in to Baack to see it; until then this is the live page.":"Log in with your Baack account. The editor opens when you have logged in."),u=o("button","","Close");if(u.type="button",i.append(d,c),r){let a=o("iframe");a.title="Log in to Baack",a.src=r;let P=o("div","login");P.append(a),i.append(P)}else i.append(o("p","message","The login page is not available. Log in at Baack, then reload this page."));let T=o("div","actions");T.append(u),i.append(T),n.append(i),e.root.append(n);let p,y=()=>{clearTimeout(p),n.remove()};u.addEventListener("click",y),n.addEventListener("keydown",a=>{a.key==="Escape"&&y()}),u.focus();let w=async()=>{try{let a=await I.clientContext();if(a.hasSession===!0){y(),M(a,t);return}}catch{}n.isConnected&&(p=setTimeout(()=>{w()},b))};p=setTimeout(()=>{w()},b)}function N(r){let t=new l,e=(n,i)=>({x:n.clientX,y:n.clientY,time:i.timeStamp});document.addEventListener("touchstart",n=>{let i=n.touches[0];n.touches.length!==1||!i||!U(n.target)?t.cancel():t.down(e(i,n),window.innerWidth)},{passive:!0}),document.addEventListener("touchend",n=>{let i=n.changedTouches[0];n.touches.length===0&&i&&t.up(e(i,n),window.innerWidth)&&r()},{passive:!0}),document.addEventListener("touchcancel",()=>t.cancel(),{passive:!0})}function U(r){for(let t=r instanceof Element?r:null;t;t=t.parentElement){if(t.matches('input, textarea, select, [contenteditable]:not([contenteditable="false"])'))return!1;let e=getComputedStyle(t).overflowX;if((e==="auto"||e==="scroll")&&t.scrollWidth>t.clientWidth)return!1}return!0}function D(){try{return window.localStorage.getItem(k)==="1"}catch{return!1}}function F(){try{window.localStorage.setItem(k,"1")}catch{}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{S()},{once:!0}):S();
2
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/swipe.ts", "../src/core/transport.ts", "../src/loader.ts"],
4
+ "sourcesContent": ["// The touch gesture that asks for the editor: two quick swipes to the left\n// across the middle of the screen. It starts away from both edges, where iOS\n// and Android take a swipe as Back, and is mostly horizontal, so scrolling\n// never counts. Pure, so the rules are tested without a browser.\n\n/** How far a swipe must travel, as a share of the screen's width. */\nconst MIN_DISTANCE = 0.3;\n/** The edge bands a swipe may not start in, as a share of the width. */\nconst EDGE = 0.15;\n/** The longest a single swipe may take. */\nconst MAX_SWIPE_MS = 600;\n/** The longest gap between the end of the first swipe and the start of the second. */\nconst MAX_GAP_MS = 800;\n\nexport interface TouchPoint {\n x: number;\n y: number;\n time: number;\n}\n\nexport class DoubleSwipe {\n private start: TouchPoint | undefined;\n private firstEnded: number | undefined;\n\n /** A single finger touches down; `width` is the screen's width. */\n down(point: TouchPoint, width: number): void {\n const fromEdge = point.x < width * EDGE || point.x > width * (1 - EDGE);\n if (this.firstEnded !== undefined && point.time - this.firstEnded > MAX_GAP_MS) this.firstEnded = undefined;\n this.start = fromEdge ? undefined : point;\n }\n\n /** Another finger, or a touch that cannot be a swipe (in a field, a carousel): the gesture starts again. */\n cancel(): void {\n this.start = undefined;\n this.firstEnded = undefined;\n }\n\n /** The finger lifts. True when this completes the second swipe. */\n up(point: TouchPoint, width: number): boolean {\n const start = this.start;\n this.start = undefined;\n if (!start) return false;\n const dx = point.x - start.x;\n const dy = point.y - start.y;\n const swipe = -dx >= width * MIN_DISTANCE && Math.abs(dy) <= Math.abs(dx) / 2 && point.time - start.time <= MAX_SWIPE_MS;\n if (!swipe) {\n this.firstEnded = undefined;\n return false;\n }\n if (this.firstEnded !== undefined) {\n this.firstEnded = undefined;\n return true;\n }\n this.firstEnded = point.time;\n return false;\n }\n}\n", "// The editor's only route to the API. Failures are never swallowed: a non-2xx\n// response rejects with BaackApiError (carrying the HTTP status), and a\n// network failure rejects with fetch's own error.\n\nimport { BaackClient, Endpoint, type ClientContext, type Company, type Entity, type Pagination, type Search, type Task } from '@baack-software/baack-ts-client';\nimport type { ContentItem, ItemRepresentation, TypeEntry } from './registry.ts';\n\nexport interface ItemHistory<I extends ContentItem> {\n item?: I | null;\n history: I[];\n pagination?: Pagination | null;\n url: string;\n}\n\nexport interface EntityViewOptions {\n /** 'LATEST' or an ISO timestamp. Omit for the live view. Needs a session. */\n version?: string;\n /**\n * The language and variant to look up by page path, or, with a URN, to hold\n * to: the view treats a URN as a locator and may otherwise return another\n * language's entity. Read entities in scope through `ScopedViews`.\n */\n language?: string;\n variant?: string;\n}\n\n/** What is sent to create an entity. The server assigns the URN and scopes the name under the owner. */\nexport interface NewEntity {\n owner: { urn: string };\n status: 'DRAFT_UNPUBLISHED';\n /** A page path such as /blog/hello. */\n name: string;\n language: string;\n variant: string;\n}\n\n/** Entity URNs found by a search. `complete` is false when the search was still partial after polling. */\nexport interface EntitySearch {\n urns: string[];\n complete: boolean;\n}\n\n/** How often, and how many times, a partial search is read again (as the legacy client does). */\nconst SEARCH_POLL_MS = 500;\nconst SEARCH_POLLS = 10;\n\nexport interface Transport {\n clientContext(): Promise<ClientContext>;\n /** By entity URN, or by page path (`/blog/hello`) with language and variant. */\n entityView(scope: string, options?: EntityViewOptions): Promise<Entity>;\n createEntity(entity: NewEntity): Promise<Entity>;\n /** The companies the user may administer. */\n companies(): Promise<Company[]>;\n /** Every entity the owner has: the search returns them all, unfiltered, by URN. */\n searchEntities(owner: string): Promise<EntitySearch>;\n create<I extends ContentItem>(entry: TypeEntry<I>, item: ItemRepresentation<I>): Promise<I>;\n read<I extends ContentItem>(entry: TypeEntry<I>, urn: string): Promise<I>;\n update<I extends ContentItem>(entry: TypeEntry<I>, urn: string, item: ItemRepresentation<I>): Promise<I>;\n remove(entry: TypeEntry, urn: string): Promise<void>;\n /** One page of an item's versions, newest first; `after` continues from the previous page. */\n history<I extends ContentItem>(entry: TypeEntry<I>, urn: string, after?: string): Promise<ItemHistory<I>>;\n /** Makes a version live (moves the live pointer). The body is the version's item. */\n publishVersion<I extends ContentItem>(entry: TypeEntry<I>, item: I): Promise<ItemHistory<I>>;\n /** The entity's own fields and status, for the lifecycle. */\n readEntity(urn: string): Promise<Entity>;\n /** A lifecycle verb: the entity's fields with a new status. Item arrays are never sent. */\n updateEntity(urn: string, entity: EntityUpdate): Promise<Entity>;\n createTask(task: Partial<Task>): Promise<Task>;\n /** Stages one file for one slot (DEFAULT, MEDIUM or LARGE) of an image version whose slot is empty. */\n uploadImageFile(imageItemUrn: string, size: 'DEFAULT' | 'MEDIUM' | 'LARGE', file: File): Promise<unknown>;\n}\n\n/** The fields of an entity a lifecycle change sends. */\nexport interface EntityUpdate {\n owner: { urn: string };\n name: string;\n language: string;\n variant: string;\n status: 'PUBLISH' | 'DRAFT_UNPUBLISHED';\n publishTimestamp?: string;\n}\n\n/** Talks to Baack directly with the user's session cookie. */\nexport class DirectTransport implements Transport {\n private readonly client: BaackClient;\n\n constructor(baseUrl: string) {\n this.client = new BaackClient({ baseUrl, credentials: 'include' });\n }\n\n clientContext(): Promise<ClientContext> {\n return this.client.read<ClientContext>(Endpoint.CLIENT_CONTEXT, '');\n }\n\n entityView(scope: string, options: EntityViewOptions = {}): Promise<Entity> {\n return this.client.read<Entity>(Endpoint.ENTITY_VIEW, scope, {\n version: options.version,\n language: options.language,\n variant: options.variant,\n });\n }\n\n createEntity(entity: NewEntity): Promise<Entity> {\n return this.client.create<Entity>(Endpoint.ENTITY, entity);\n }\n\n async companies(): Promise<Company[]> {\n return (await this.client.read<{ companies?: Company[] }>(Endpoint.COMPANIES, '')).companies ?? [];\n }\n\n async searchEntities(owner: string): Promise<EntitySearch> {\n // `order: NAME` may not be implemented yet; it is harmless to ask.\n // A link is sent by URN only (writes are permissive).\n let result: Search = await this.client.search({ owner: { urn: owner } as Company, includeScopes: ['ENTITY'], order: 'NAME' });\n for (let poll = 0; result.status !== 'FULL_RESULT' && result.urn && poll < SEARCH_POLLS; poll += 1) {\n await new Promise((resolve) => setTimeout(resolve, SEARCH_POLL_MS));\n result = await this.client.searchResult(result.urn);\n }\n const complete = result.status === 'FULL_RESULT';\n const urns = entityUrns(result);\n // Later pages of a full result.\n while (complete && result.urn && result.pagination?.isMorePages && result.pagination.after) {\n result = await this.client.searchResult(result.urn, result.pagination.after);\n urns.push(...entityUrns(result));\n }\n return { urns: [...new Set(urns)], complete };\n }\n\n create<I extends ContentItem>(entry: TypeEntry<I>, item: ItemRepresentation<I>): Promise<I> {\n return this.client.create<I>(entry.endpoint, item);\n }\n\n read<I extends ContentItem>(entry: TypeEntry<I>, urn: string): Promise<I> {\n return this.client.read<I>(entry.endpoint, urn);\n }\n\n update<I extends ContentItem>(entry: TypeEntry<I>, urn: string, item: ItemRepresentation<I>): Promise<I> {\n return this.client.update<I>(entry.endpoint, urn, item);\n }\n\n async remove(entry: TypeEntry, urn: string): Promise<void> {\n await this.client.delete(entry.endpoint, urn);\n }\n\n history<I extends ContentItem>(entry: TypeEntry<I>, urn: string, after?: string): Promise<ItemHistory<I>> {\n return this.client.read<ItemHistory<I>>(entry.historyEndpoint, urn, { after });\n }\n\n publishVersion<I extends ContentItem>(entry: TypeEntry<I>, item: I): Promise<ItemHistory<I>> {\n return this.client.update<ItemHistory<I>>(entry.historyEndpoint, item.urn!, item);\n }\n\n readEntity(urn: string): Promise<Entity> {\n return this.client.read<Entity>(Endpoint.ENTITY, urn);\n }\n\n updateEntity(urn: string, entity: EntityUpdate): Promise<Entity> {\n return this.client.update<Entity>(Endpoint.ENTITY, urn, entity);\n }\n\n createTask(task: Partial<Task>): Promise<Task> {\n return this.client.create<Task>(Endpoint.TASK, task);\n }\n\n uploadImageFile(imageItemUrn: string, size: 'DEFAULT' | 'MEDIUM' | 'LARGE', file: File): Promise<unknown> {\n const form = new FormData();\n form.append('imageItemUrn', imageItemUrn);\n form.append('imageItemSize', size);\n form.append('src', file, file.name);\n return this.client.upload(Endpoint.IMAGE_FILE, form);\n }\n}\n\nfunction entityUrns(result: Search): string[] {\n return (result.items ?? []).filter((item) => item.type === 'ENTITY' && item.urn).map((item) => item.urn);\n}\n", "// The script a site includes. Anonymous visitors cost nothing: the loader\n// makes no API call unless this browser has used the editor before, or\n// someone asks for it (`?edit`, `?version=\u2026`, Alt+Shift+E, or two swipes to\n// the left on a touch screen). With a session\n// it offers \"Edit page\", and the full editor loads only when pressed. Without\n// one, when asked, it opens a login modal with Baack's login iframe.\n\nimport type { ClientContext } from '@baack-software/baack-ts-client';\nimport { readConfig } from './config.ts';\nimport { DoubleSwipe } from './core/swipe.ts';\nimport { DirectTransport } from './core/transport.ts';\nimport { createHost, el, type EditorHost } from './ui/host.ts';\nimport { createLauncher } from './ui/launcher.ts';\nimport type { ReadMode } from './view.ts';\n\ndeclare global {\n interface Window {\n baackEditorLoaded?: boolean;\n }\n}\n\n/** Set once this browser has had an editor session, so later visits check for one. */\nconst FLAG = 'baack-editor:editor';\n/** While the login modal is open, how often to check whether the login has completed. */\nconst LOGIN_POLL_MS = 2000;\n\nconst transport = new DirectTransport(readConfig().baseUrl);\nlet started = false;\nlet checking = false;\n\nasync function boot(): Promise<void> {\n if (window.baackEditorLoaded) return;\n window.baackEditorLoaded = true;\n\n // ?version=LATEST or ?version=<epoch ms> asks for drafts; ?edit asks for the editor.\n const params = new URLSearchParams(location.search);\n const version = params.get('version');\n const mode: ReadMode | undefined = version === 'LATEST' ? 'LATEST' : version && /^\\d+$/.test(version) ? Number(version) : undefined;\n const asked = params.has('edit') || mode !== undefined;\n\n document.addEventListener('keydown', (event) => {\n if (event.altKey && event.shiftKey && event.code === 'KeyE') {\n event.preventDefault();\n void check(true, mode);\n }\n });\n watchSwipes(() => void check(true, mode));\n if (asked || readFlag()) await check(asked, mode);\n}\n\n/** Asks the API whether there is a session; offers the editor, or (when asked for) a login. */\nasync function check(explicit: boolean, mode: ReadMode | undefined): Promise<void> {\n if (started || checking) return;\n checking = true;\n let context: ClientContext;\n try {\n context = await transport.clientContext();\n } catch (error) {\n console.warn('Baack editor: could not read the client context; editing is unavailable.', error);\n return;\n } finally {\n checking = false;\n }\n if (context.hasSession === true) {\n offer(context, mode);\n } else if (explicit) {\n // Only a session may see drafts: without one the page stays as built.\n openLogin(context.loginIframeSrc, mode);\n }\n}\n\nfunction offer(context: ClientContext, mode: ReadMode | undefined): void {\n if (started) return;\n started = true;\n writeFlag();\n const host = createHost();\n const button = createLauncher(host);\n const start = async () => {\n button.disabled = true;\n const editor = await import('./editor.ts');\n editor.start({ transport, host, context, ...(mode !== undefined ? { mode } : {}) });\n };\n if (mode !== undefined) {\n void start();\n } else {\n button.addEventListener('click', () => void start(), { once: true });\n }\n}\n\n/** A modal with Baack's login iframe. Checks for the session until the login completes, then offers the editor. */\nfunction openLogin(iframeSrc: string | null | undefined, mode: ReadMode | undefined): void {\n const host: EditorHost = createHost();\n if (host.root.querySelector('.login-modal')) return;\n const backdrop = el('div', 'login-modal');\n const dialog = el('div', 'panel modal');\n dialog.setAttribute('role', 'dialog');\n dialog.setAttribute('aria-modal', 'true');\n dialog.setAttribute('aria-label', 'Log in to edit');\n const title = el('div', 'title', mode !== undefined ? 'Log in to see draft content' : 'Log in to edit this page');\n const text = el(\n 'p',\n 'message info',\n mode !== undefined\n ? 'This link shows draft content. Log in to Baack to see it; until then this is the live page.'\n : 'Log in with your Baack account. The editor opens when you have logged in.',\n );\n const close = el('button', '', 'Close');\n close.type = 'button';\n dialog.append(title, text);\n if (iframeSrc) {\n const frame = el('iframe');\n frame.title = 'Log in to Baack';\n frame.src = iframeSrc;\n const login = el('div', 'login');\n login.append(frame);\n dialog.append(login);\n } else {\n dialog.append(el('p', 'message', 'The login page is not available. Log in at Baack, then reload this page.'));\n }\n const actions = el('div', 'actions');\n actions.append(close);\n dialog.append(actions);\n backdrop.append(dialog);\n host.root.append(backdrop);\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const dismiss = () => {\n clearTimeout(timer);\n backdrop.remove();\n };\n close.addEventListener('click', dismiss);\n backdrop.addEventListener('keydown', (event) => {\n if (event.key === 'Escape') dismiss();\n });\n close.focus();\n\n const poll = async () => {\n try {\n const context = await transport.clientContext();\n if (context.hasSession === true) {\n dismiss();\n offer(context, mode);\n return;\n }\n } catch {\n // Keep waiting; the modal stays until the login completes or it is closed.\n }\n if (backdrop.isConnected) timer = setTimeout(() => void poll(), LOGIN_POLL_MS);\n };\n timer = setTimeout(() => void poll(), LOGIN_POLL_MS);\n}\n\n/**\n * On touch screens, two quick swipes to the left across the middle of the page ask for the editor, as Alt+Shift+E\n * does on a keyboard. Passive listeners, so the page scrolls as usual and visitors pay nothing.\n */\nfunction watchSwipes(onSwipe: () => void): void {\n const gesture = new DoubleSwipe();\n const point = (touch: Touch, event: TouchEvent) => ({ x: touch.clientX, y: touch.clientY, time: event.timeStamp });\n document.addEventListener(\n 'touchstart',\n (event) => {\n const touch = event.touches[0];\n if (event.touches.length !== 1 || !touch || !swipeable(event.target)) gesture.cancel();\n else gesture.down(point(touch, event), window.innerWidth);\n },\n { passive: true },\n );\n document.addEventListener(\n 'touchend',\n (event) => {\n const touch = event.changedTouches[0];\n if (event.touches.length === 0 && touch && gesture.up(point(touch, event), window.innerWidth)) onSwipe();\n },\n { passive: true },\n );\n document.addEventListener('touchcancel', () => gesture.cancel(), { passive: true });\n}\n\n/** A swipe in a field, or in something that scrolls sideways (a carousel), belongs to it. */\nfunction swipeable(target: EventTarget | null): boolean {\n for (let node = target instanceof Element ? target : null; node; node = node.parentElement) {\n if (node.matches('input, textarea, select, [contenteditable]:not([contenteditable=\"false\"])')) return false;\n const overflow = getComputedStyle(node).overflowX;\n if ((overflow === 'auto' || overflow === 'scroll') && node.scrollWidth > node.clientWidth) return false;\n }\n return true;\n}\n\nfunction readFlag(): boolean {\n try {\n return window.localStorage.getItem(FLAG) === '1';\n } catch {\n return false;\n }\n}\n\nfunction writeFlag(): void {\n try {\n window.localStorage.setItem(FLAG, '1');\n } catch {\n // Without storage, later visits need ?edit or Alt+Shift+E.\n }\n}\n\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => void boot(), { once: true });\n} else {\n void boot();\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["DoubleSwipe", "point", "width", "fromEdge", "start", "dx", "dy", "SEARCH_POLL_MS", "SEARCH_POLLS", "DirectTransport", "baseUrl", "BaackClient", "Endpoint", "scope", "options", "entity", "owner", "result", "poll", "resolve", "complete", "urns", "entityUrns", "entry", "item", "urn", "after", "task", "imageItemUrn", "size", "file", "form", "FLAG", "LOGIN_POLL_MS", "transport", "DirectTransport", "readConfig", "started", "checking", "boot", "params", "version", "mode", "asked", "event", "check", "watchSwipes", "readFlag", "explicit", "context", "error", "offer", "openLogin", "writeFlag", "host", "createHost", "button", "createLauncher", "start", "iframeSrc", "backdrop", "el", "dialog", "title", "text", "close", "frame", "login", "actions", "timer", "dismiss", "poll", "onSwipe", "gesture", "DoubleSwipe", "point", "touch", "swipeable", "target", "node", "overflow"]
7
+ }
package/package.json CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
2
  "name": "@baack-software/baack-ts-editor",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Edit Baack content in place, on your own site's pages",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "homepage": "https://github.com/Baack-Software/baack-ts-editor#readme",
8
+ "bugs": {
9
+ "url": "https://github.com/Baack-Software/baack-ts-editor/issues"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/Baack-Software/baack-ts-editor.git"
14
+ },
15
+ "files": [
16
+ "dist/loader.js",
17
+ "dist/loader.js.map",
18
+ "dist/editor.js",
19
+ "dist/editor.js.map",
20
+ "dist/chunks"
21
+ ],
22
+ "scripts": {
23
+ "build": "node build.mjs",
24
+ "typecheck": "tsc --noEmit",
25
+ "serve": "npm run build && node mock/server.ts",
26
+ "test": "npm run typecheck && npm run test:mock && npm run test:browser",
27
+ "test:mock": "node --test \"mock/**/*.test.ts\" \"src/**/*.test.ts\"",
28
+ "test:browser": "playwright test",
29
+ "prepublishOnly": "node build.mjs --minify"
30
+ },
31
+ "dependencies": {
32
+ "@baack-software/baack-ts-client": "^0.0.2",
33
+ "@baack-software/baack-ts-components": "^0.0.1"
34
+ },
35
+ "devDependencies": {
36
+ "@playwright/test": "~1.63.0",
37
+ "@types/node": "^24.19.1",
38
+ "@types/react": "^19.3.0",
39
+ "@types/react-dom": "^19.3.0",
40
+ "esbuild": "^0.28.2",
41
+ "react": "^19.3.0",
42
+ "react-dom": "^19.3.0",
43
+ "typescript": "^7.0.2"
44
+ }
45
+ }