@agimon-ai/doompi-web-components 0.0.1-alpha.0 → 0.0.1-alpha.3
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 +25 -6
- package/dist/components/Breadcrumb.d.cts +37 -0
- package/dist/components/Breadcrumb.d.cts.map +1 -0
- package/dist/components/CodeEditor.d.cts +6 -0
- package/dist/components/CodeEditor.d.cts.map +1 -0
- package/dist/components/Dialog.d.cts.map +1 -1
- package/dist/components/MediaPreview.d.cts +25 -0
- package/dist/components/MediaPreview.d.cts.map +1 -0
- package/dist/icons/icons.d.cts +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +8 -2
- package/dist/index.d.mts +8 -2
- package/dist/index.mjs +1 -1
- package/dist/lib/editorLanguage.d.cts +22 -0
- package/dist/lib/editorLanguage.d.cts.map +1 -0
- package/dist/lib/media.d.cts +12 -0
- package/dist/lib/media.d.cts.map +1 -0
- package/dist/src/components/Breadcrumb.cjs +2 -0
- package/dist/src/components/Breadcrumb.cjs.map +1 -0
- package/dist/src/components/Breadcrumb.d.mts +37 -0
- package/dist/src/components/Breadcrumb.d.mts.map +1 -0
- package/dist/src/components/Breadcrumb.mjs +2 -0
- package/dist/src/components/Breadcrumb.mjs.map +1 -0
- package/dist/src/components/CodeEditor.cjs +2 -0
- package/dist/src/components/CodeEditor.cjs.map +1 -0
- package/dist/src/components/CodeEditor.d.mts +6 -0
- package/dist/src/components/CodeEditor.d.mts.map +1 -0
- package/dist/src/components/CodeEditor.mjs +2 -0
- package/dist/src/components/CodeEditor.mjs.map +1 -0
- package/dist/src/components/CodeEditorView.cjs +2 -0
- package/dist/src/components/CodeEditorView.cjs.map +1 -0
- package/dist/src/components/CodeEditorView.mjs +2 -0
- package/dist/src/components/CodeEditorView.mjs.map +1 -0
- package/dist/src/components/Dialog.cjs +1 -1
- package/dist/src/components/Dialog.cjs.map +1 -1
- package/dist/src/components/Dialog.d.mts.map +1 -1
- package/dist/src/components/Dialog.mjs +1 -1
- package/dist/src/components/Dialog.mjs.map +1 -1
- package/dist/src/components/EmptyState.cjs +1 -1
- package/dist/src/components/EmptyState.cjs.map +1 -1
- package/dist/src/components/EmptyState.mjs +1 -1
- package/dist/src/components/EmptyState.mjs.map +1 -1
- package/dist/src/components/MediaPreview.cjs +2 -0
- package/dist/src/components/MediaPreview.cjs.map +1 -0
- package/dist/src/components/MediaPreview.d.mts +25 -0
- package/dist/src/components/MediaPreview.d.mts.map +1 -0
- package/dist/src/components/MediaPreview.mjs +2 -0
- package/dist/src/components/MediaPreview.mjs.map +1 -0
- package/dist/src/components/Popover.cjs +1 -1
- package/dist/src/components/Popover.cjs.map +1 -1
- package/dist/src/components/Popover.mjs +1 -1
- package/dist/src/components/Popover.mjs.map +1 -1
- package/dist/src/icons/icons.cjs +1 -1
- package/dist/src/icons/icons.d.mts +2 -2
- package/dist/src/icons/icons.mjs +1 -1
- package/dist/src/lib/editorLanguage.cjs +2 -0
- package/dist/src/lib/editorLanguage.cjs.map +1 -0
- package/dist/src/lib/editorLanguage.d.mts +22 -0
- package/dist/src/lib/editorLanguage.d.mts.map +1 -0
- package/dist/src/lib/editorLanguage.mjs +2 -0
- package/dist/src/lib/editorLanguage.mjs.map +1 -0
- package/dist/src/lib/editorTheme.cjs +2 -0
- package/dist/src/lib/editorTheme.cjs.map +1 -0
- package/dist/src/lib/editorTheme.mjs +2 -0
- package/dist/src/lib/editorTheme.mjs.map +1 -0
- package/dist/src/lib/media.cjs +2 -0
- package/dist/src/lib/media.cjs.map +1 -0
- package/dist/src/lib/media.d.mts +12 -0
- package/dist/src/lib/media.d.mts.map +1 -0
- package/dist/src/lib/media.mjs +2 -0
- package/dist/src/lib/media.mjs.map +1 -0
- package/dist/src/types/editor.cjs +2 -0
- package/dist/src/types/editor.cjs.map +1 -0
- package/dist/src/types/editor.d.mts +44 -0
- package/dist/src/types/editor.d.mts.map +1 -0
- package/dist/src/types/editor.mjs +2 -0
- package/dist/src/types/editor.mjs.map +1 -0
- package/dist/types/editor.d.cts +44 -0
- package/dist/types/editor.d.cts.map +1 -0
- package/package.json +16 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeEditorView.cjs","names":["EditorView","DOOM_EDITOR_STYLES","HighlightStyle","tags","DOOM_SYNTAX_STYLES","lineNumbers","highlightActiveLineGutter","foldGutter","highlightActiveLine","drawSelection","rectangularSelection","indentOnInput","bracketMatching","history","search","highlightSelectionMatches","keymap","defaultKeymap","historyKeymap","searchKeymap","foldKeymap","indentWithTab","syntaxHighlighting","useRef","Compartment","EditorState","grammarKeyOf","loadGrammar","cn"],"sources":["../../../src/components/CodeEditorView.tsx"],"sourcesContent":["import { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';\nimport {\n bracketMatching,\n foldGutter,\n foldKeymap,\n HighlightStyle,\n indentOnInput,\n syntaxHighlighting,\n} from '@codemirror/language';\nimport { highlightSelectionMatches, search, searchKeymap } from '@codemirror/search';\nimport { Compartment, EditorState } from '@codemirror/state';\nimport {\n drawSelection,\n EditorView,\n highlightActiveLine,\n highlightActiveLineGutter,\n keymap,\n lineNumbers,\n rectangularSelection,\n} from '@codemirror/view';\nimport { tags } from '@lezer/highlight';\nimport { useEffect, useRef } from 'react';\nimport { cn } from '../lib/cn.ts';\nimport { grammarKeyOf, loadGrammar } from '../lib/editorLanguage.ts';\nimport { DOOM_EDITOR_STYLES, DOOM_SYNTAX_STYLES } from '../lib/editorTheme.ts';\nimport type { CodeEditorProps } from '../types/editor.ts';\n\n/**\n * The editor itself, mounted on a real CodeMirror view.\n *\n * Nothing imports this module directly: `CodeEditor` reaches it through a lazy\n * import so the whole editor, and every grammar under it, stays out of the\n * cockpit's first load. Behaviour lives here rather than in that wrapper so\n * the split costs one file and no indirection.\n *\n * The three things a caller can change after mount each sit in their own\n * compartment. Reconfiguring one is a transaction; rebuilding the editor would\n * throw away the undo history, the scroll position and the cursor, which is\n * what a reader loses if a parent re-render is allowed to remount this.\n */\n\n/** Not a colour or a layout choice: how CodeMirror is told to draw the doom palette. */\nconst DOOM_THEME = EditorView.theme(DOOM_EDITOR_STYLES);\n\nconst DOOM_HIGHLIGHT = HighlightStyle.define([\n { tag: tags.comment, ...DOOM_SYNTAX_STYLES.comment },\n { tag: tags.keyword, ...DOOM_SYNTAX_STYLES.keyword },\n { tag: [tags.atom, tags.bool, tags.null, tags.self], ...DOOM_SYNTAX_STYLES.constant },\n { tag: tags.number, ...DOOM_SYNTAX_STYLES.literal },\n { tag: [tags.string, tags.special(tags.string), tags.character], ...DOOM_SYNTAX_STYLES.string },\n { tag: tags.regexp, ...DOOM_SYNTAX_STYLES.regexp },\n { tag: tags.operator, ...DOOM_SYNTAX_STYLES.operator },\n { tag: tags.punctuation, ...DOOM_SYNTAX_STYLES.punctuation },\n { tag: tags.variableName, ...DOOM_SYNTAX_STYLES.variable },\n { tag: tags.propertyName, ...DOOM_SYNTAX_STYLES.property },\n { tag: [tags.function(tags.variableName), tags.function(tags.propertyName)], ...DOOM_SYNTAX_STYLES.callable },\n { tag: [tags.typeName, tags.className, tags.namespace], ...DOOM_SYNTAX_STYLES.type },\n { tag: tags.tagName, ...DOOM_SYNTAX_STYLES.tag },\n { tag: tags.attributeName, ...DOOM_SYNTAX_STYLES.attribute },\n { tag: [tags.meta, tags.processingInstruction], ...DOOM_SYNTAX_STYLES.meta },\n { tag: tags.heading, ...DOOM_SYNTAX_STYLES.heading },\n { tag: [tags.link, tags.url], ...DOOM_SYNTAX_STYLES.link },\n { tag: tags.emphasis, ...DOOM_SYNTAX_STYLES.emphasis },\n { tag: tags.strong, ...DOOM_SYNTAX_STYLES.strong },\n { tag: tags.strikethrough, ...DOOM_SYNTAX_STYLES.strikethrough },\n { tag: tags.invalid, ...DOOM_SYNTAX_STYLES.invalid },\n]);\n\n/** Everything that never changes for the life of an editor. */\nconst FIXED_EXTENSIONS = [\n lineNumbers(),\n highlightActiveLineGutter(),\n foldGutter(),\n highlightActiveLine(),\n drawSelection(),\n rectangularSelection(),\n indentOnInput(),\n bracketMatching(),\n history(),\n search({ top: true }),\n highlightSelectionMatches(),\n // Tab indents rather than leaving the editor. That trades a keyboard user's\n // escape route for the behaviour every other editor has, so it is last in\n // the keymap and Escape then Tab still moves focus out.\n keymap.of([...defaultKeymap, ...historyKeymap, ...searchKeymap, ...foldKeymap, indentWithTab]),\n syntaxHighlighting(DOOM_HIGHLIGHT),\n DOOM_THEME,\n];\n\nexport function CodeEditorView({\n value,\n path,\n readOnly = false,\n lineWrapping = true,\n className,\n onChange,\n onSelect,\n 'data-testid': testId,\n}: CodeEditorProps) {\n const host = useRef<HTMLDivElement>(null);\n const view = useRef<EditorView | null>(null);\n // The callbacks are new objects on every parent render. Reading them through\n // a ref is what lets the editor be built once and still call the current\n // pair, rather than being rebuilt whenever the parent re-renders.\n const handlers = useRef({ onChange, onSelect });\n const compartments = useRef({\n language: new Compartment(),\n readOnly: new Compartment(),\n wrapping: new Compartment(),\n });\n\n useEffect(() => {\n handlers.current = { onChange, onSelect };\n });\n\n useEffect(() => {\n const parent = host.current;\n if (parent === null) return;\n const { language, readOnly: readOnlyPart, wrapping } = compartments.current;\n const editor = new EditorView({\n parent,\n state: EditorState.create({\n // The initial document only; every later change arrives as a\n // transaction from the effect below.\n doc: value,\n extensions: [\n ...FIXED_EXTENSIONS,\n language.of([]),\n readOnlyPart.of([]),\n wrapping.of([]),\n EditorView.updateListener.of((update) => {\n if (update.docChanged) handlers.current.onChange?.(update.state.doc.toString());\n if (!update.selectionSet && !update.docChanged) return;\n const report = handlers.current.onSelect;\n if (report === undefined) return;\n const range = update.state.selection.main;\n report({\n text: update.state.sliceDoc(range.from, range.to),\n startLine: update.state.doc.lineAt(range.from).number,\n endLine: update.state.doc.lineAt(range.to).number,\n });\n }),\n ],\n }),\n });\n view.current = editor;\n return () => {\n editor.destroy();\n view.current = null;\n };\n // Built once. `value` seeds the document and the sync effect owns it after that.\n }, []);\n\n useEffect(() => {\n const editor = view.current;\n // A caller that echoes onChange back into `value` would otherwise replace\n // the document on every keystroke and drop the cursor to the end.\n if (editor === null || editor.state.doc.toString() === value) return;\n editor.dispatch({ changes: { from: 0, to: editor.state.doc.length, insert: value } });\n }, [value]);\n\n useEffect(() => {\n view.current?.dispatch({\n effects: compartments.current.readOnly.reconfigure([\n EditorState.readOnly.of(readOnly),\n EditorView.editable.of(!readOnly),\n ]),\n });\n }, [readOnly]);\n\n useEffect(() => {\n view.current?.dispatch({\n effects: compartments.current.wrapping.reconfigure(lineWrapping ? EditorView.lineWrapping : []),\n });\n }, [lineWrapping]);\n\n useEffect(() => {\n const key = path === undefined ? undefined : grammarKeyOf(path);\n const { language } = compartments.current;\n if (key === undefined) {\n view.current?.dispatch({ effects: language.reconfigure([]) });\n return;\n }\n let cancelled = false;\n void loadGrammar(key)\n .then((grammar) => {\n if (!cancelled) view.current?.dispatch({ effects: language.reconfigure(grammar) });\n })\n .catch(() => {\n // A grammar is a separate chunk over the network, and the cockpit is\n // often read through a tunnel. Losing it costs syntax colour, not the\n // file, so fall back to plain text rather than failing the pane.\n if (!cancelled) view.current?.dispatch({ effects: language.reconfigure([]) });\n });\n return () => {\n cancelled = true;\n };\n }, [path]);\n\n return <div ref={host} data-testid={testId} className={cn('min-h-0 overflow-hidden', className)} />;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{cn as e}from"../lib/cn.mjs";import{grammarKeyOf as t,loadGrammar as n}from"../lib/editorLanguage.mjs";import{DOOM_EDITOR_STYLES as r,DOOM_SYNTAX_STYLES as i}from"../lib/editorTheme.mjs";import{jsx as a}from"react/jsx-runtime";import{useEffect as o,useRef as s}from"react";import{defaultKeymap as c,history as l,historyKeymap as u,indentWithTab as d}from"@codemirror/commands";import{HighlightStyle as f,bracketMatching as p,foldGutter as m,foldKeymap as h,indentOnInput as g,syntaxHighlighting as _}from"@codemirror/language";import{highlightSelectionMatches as v,search as y,searchKeymap as b}from"@codemirror/search";import{Compartment as x,EditorState as S}from"@codemirror/state";import{EditorView as C,drawSelection as w,highlightActiveLine as T,highlightActiveLineGutter as E,keymap as D,lineNumbers as O,rectangularSelection as k}from"@codemirror/view";import{tags as A}from"@lezer/highlight";const j=C.theme(r),M=f.define([{tag:A.comment,...i.comment},{tag:A.keyword,...i.keyword},{tag:[A.atom,A.bool,A.null,A.self],...i.constant},{tag:A.number,...i.literal},{tag:[A.string,A.special(A.string),A.character],...i.string},{tag:A.regexp,...i.regexp},{tag:A.operator,...i.operator},{tag:A.punctuation,...i.punctuation},{tag:A.variableName,...i.variable},{tag:A.propertyName,...i.property},{tag:[A.function(A.variableName),A.function(A.propertyName)],...i.callable},{tag:[A.typeName,A.className,A.namespace],...i.type},{tag:A.tagName,...i.tag},{tag:A.attributeName,...i.attribute},{tag:[A.meta,A.processingInstruction],...i.meta},{tag:A.heading,...i.heading},{tag:[A.link,A.url],...i.link},{tag:A.emphasis,...i.emphasis},{tag:A.strong,...i.strong},{tag:A.strikethrough,...i.strikethrough},{tag:A.invalid,...i.invalid}]),N=[O(),E(),m(),T(),w(),k(),g(),p(),l(),y({top:!0}),v(),D.of([...c,...u,...b,...h,d]),_(M),j];function P({value:r,path:i,readOnly:c=!1,lineWrapping:l=!0,className:u,onChange:d,onSelect:f,"data-testid":p}){let m=s(null),h=s(null),g=s({onChange:d,onSelect:f}),_=s({language:new x,readOnly:new x,wrapping:new x});return o(()=>{g.current={onChange:d,onSelect:f}}),o(()=>{let e=m.current;if(e===null)return;let{language:t,readOnly:n,wrapping:i}=_.current,a=new C({parent:e,state:S.create({doc:r,extensions:[...N,t.of([]),n.of([]),i.of([]),C.updateListener.of(e=>{if(e.docChanged&&g.current.onChange?.(e.state.doc.toString()),!e.selectionSet&&!e.docChanged)return;let t=g.current.onSelect;if(t===void 0)return;let n=e.state.selection.main;t({text:e.state.sliceDoc(n.from,n.to),startLine:e.state.doc.lineAt(n.from).number,endLine:e.state.doc.lineAt(n.to).number})})]})});return h.current=a,()=>{a.destroy(),h.current=null}},[]),o(()=>{let e=h.current;e!==null&&e.state.doc.toString()!==r&&e.dispatch({changes:{from:0,to:e.state.doc.length,insert:r}})},[r]),o(()=>{h.current?.dispatch({effects:_.current.readOnly.reconfigure([S.readOnly.of(c),C.editable.of(!c)])})},[c]),o(()=>{h.current?.dispatch({effects:_.current.wrapping.reconfigure(l?C.lineWrapping:[])})},[l]),o(()=>{let e=i===void 0?void 0:t(i),{language:r}=_.current;if(e===void 0){h.current?.dispatch({effects:r.reconfigure([])});return}let a=!1;return n(e).then(e=>{a||h.current?.dispatch({effects:r.reconfigure(e)})}).catch(()=>{a||h.current?.dispatch({effects:r.reconfigure([])})}),()=>{a=!0}},[i]),a(`div`,{ref:m,"data-testid":p,className:e(`min-h-0 overflow-hidden`,u)})}export{P as CodeEditorView};
|
|
2
|
+
//# sourceMappingURL=CodeEditorView.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeEditorView.mjs","names":[],"sources":["../../../src/components/CodeEditorView.tsx"],"sourcesContent":["import { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';\nimport {\n bracketMatching,\n foldGutter,\n foldKeymap,\n HighlightStyle,\n indentOnInput,\n syntaxHighlighting,\n} from '@codemirror/language';\nimport { highlightSelectionMatches, search, searchKeymap } from '@codemirror/search';\nimport { Compartment, EditorState } from '@codemirror/state';\nimport {\n drawSelection,\n EditorView,\n highlightActiveLine,\n highlightActiveLineGutter,\n keymap,\n lineNumbers,\n rectangularSelection,\n} from '@codemirror/view';\nimport { tags } from '@lezer/highlight';\nimport { useEffect, useRef } from 'react';\nimport { cn } from '../lib/cn.ts';\nimport { grammarKeyOf, loadGrammar } from '../lib/editorLanguage.ts';\nimport { DOOM_EDITOR_STYLES, DOOM_SYNTAX_STYLES } from '../lib/editorTheme.ts';\nimport type { CodeEditorProps } from '../types/editor.ts';\n\n/**\n * The editor itself, mounted on a real CodeMirror view.\n *\n * Nothing imports this module directly: `CodeEditor` reaches it through a lazy\n * import so the whole editor, and every grammar under it, stays out of the\n * cockpit's first load. Behaviour lives here rather than in that wrapper so\n * the split costs one file and no indirection.\n *\n * The three things a caller can change after mount each sit in their own\n * compartment. Reconfiguring one is a transaction; rebuilding the editor would\n * throw away the undo history, the scroll position and the cursor, which is\n * what a reader loses if a parent re-render is allowed to remount this.\n */\n\n/** Not a colour or a layout choice: how CodeMirror is told to draw the doom palette. */\nconst DOOM_THEME = EditorView.theme(DOOM_EDITOR_STYLES);\n\nconst DOOM_HIGHLIGHT = HighlightStyle.define([\n { tag: tags.comment, ...DOOM_SYNTAX_STYLES.comment },\n { tag: tags.keyword, ...DOOM_SYNTAX_STYLES.keyword },\n { tag: [tags.atom, tags.bool, tags.null, tags.self], ...DOOM_SYNTAX_STYLES.constant },\n { tag: tags.number, ...DOOM_SYNTAX_STYLES.literal },\n { tag: [tags.string, tags.special(tags.string), tags.character], ...DOOM_SYNTAX_STYLES.string },\n { tag: tags.regexp, ...DOOM_SYNTAX_STYLES.regexp },\n { tag: tags.operator, ...DOOM_SYNTAX_STYLES.operator },\n { tag: tags.punctuation, ...DOOM_SYNTAX_STYLES.punctuation },\n { tag: tags.variableName, ...DOOM_SYNTAX_STYLES.variable },\n { tag: tags.propertyName, ...DOOM_SYNTAX_STYLES.property },\n { tag: [tags.function(tags.variableName), tags.function(tags.propertyName)], ...DOOM_SYNTAX_STYLES.callable },\n { tag: [tags.typeName, tags.className, tags.namespace], ...DOOM_SYNTAX_STYLES.type },\n { tag: tags.tagName, ...DOOM_SYNTAX_STYLES.tag },\n { tag: tags.attributeName, ...DOOM_SYNTAX_STYLES.attribute },\n { tag: [tags.meta, tags.processingInstruction], ...DOOM_SYNTAX_STYLES.meta },\n { tag: tags.heading, ...DOOM_SYNTAX_STYLES.heading },\n { tag: [tags.link, tags.url], ...DOOM_SYNTAX_STYLES.link },\n { tag: tags.emphasis, ...DOOM_SYNTAX_STYLES.emphasis },\n { tag: tags.strong, ...DOOM_SYNTAX_STYLES.strong },\n { tag: tags.strikethrough, ...DOOM_SYNTAX_STYLES.strikethrough },\n { tag: tags.invalid, ...DOOM_SYNTAX_STYLES.invalid },\n]);\n\n/** Everything that never changes for the life of an editor. */\nconst FIXED_EXTENSIONS = [\n lineNumbers(),\n highlightActiveLineGutter(),\n foldGutter(),\n highlightActiveLine(),\n drawSelection(),\n rectangularSelection(),\n indentOnInput(),\n bracketMatching(),\n history(),\n search({ top: true }),\n highlightSelectionMatches(),\n // Tab indents rather than leaving the editor. That trades a keyboard user's\n // escape route for the behaviour every other editor has, so it is last in\n // the keymap and Escape then Tab still moves focus out.\n keymap.of([...defaultKeymap, ...historyKeymap, ...searchKeymap, ...foldKeymap, indentWithTab]),\n syntaxHighlighting(DOOM_HIGHLIGHT),\n DOOM_THEME,\n];\n\nexport function CodeEditorView({\n value,\n path,\n readOnly = false,\n lineWrapping = true,\n className,\n onChange,\n onSelect,\n 'data-testid': testId,\n}: CodeEditorProps) {\n const host = useRef<HTMLDivElement>(null);\n const view = useRef<EditorView | null>(null);\n // The callbacks are new objects on every parent render. Reading them through\n // a ref is what lets the editor be built once and still call the current\n // pair, rather than being rebuilt whenever the parent re-renders.\n const handlers = useRef({ onChange, onSelect });\n const compartments = useRef({\n language: new Compartment(),\n readOnly: new Compartment(),\n wrapping: new Compartment(),\n });\n\n useEffect(() => {\n handlers.current = { onChange, onSelect };\n });\n\n useEffect(() => {\n const parent = host.current;\n if (parent === null) return;\n const { language, readOnly: readOnlyPart, wrapping } = compartments.current;\n const editor = new EditorView({\n parent,\n state: EditorState.create({\n // The initial document only; every later change arrives as a\n // transaction from the effect below.\n doc: value,\n extensions: [\n ...FIXED_EXTENSIONS,\n language.of([]),\n readOnlyPart.of([]),\n wrapping.of([]),\n EditorView.updateListener.of((update) => {\n if (update.docChanged) handlers.current.onChange?.(update.state.doc.toString());\n if (!update.selectionSet && !update.docChanged) return;\n const report = handlers.current.onSelect;\n if (report === undefined) return;\n const range = update.state.selection.main;\n report({\n text: update.state.sliceDoc(range.from, range.to),\n startLine: update.state.doc.lineAt(range.from).number,\n endLine: update.state.doc.lineAt(range.to).number,\n });\n }),\n ],\n }),\n });\n view.current = editor;\n return () => {\n editor.destroy();\n view.current = null;\n };\n // Built once. `value` seeds the document and the sync effect owns it after that.\n }, []);\n\n useEffect(() => {\n const editor = view.current;\n // A caller that echoes onChange back into `value` would otherwise replace\n // the document on every keystroke and drop the cursor to the end.\n if (editor === null || editor.state.doc.toString() === value) return;\n editor.dispatch({ changes: { from: 0, to: editor.state.doc.length, insert: value } });\n }, [value]);\n\n useEffect(() => {\n view.current?.dispatch({\n effects: compartments.current.readOnly.reconfigure([\n EditorState.readOnly.of(readOnly),\n EditorView.editable.of(!readOnly),\n ]),\n });\n }, [readOnly]);\n\n useEffect(() => {\n view.current?.dispatch({\n effects: compartments.current.wrapping.reconfigure(lineWrapping ? EditorView.lineWrapping : []),\n });\n }, [lineWrapping]);\n\n useEffect(() => {\n const key = path === undefined ? undefined : grammarKeyOf(path);\n const { language } = compartments.current;\n if (key === undefined) {\n view.current?.dispatch({ effects: language.reconfigure([]) });\n return;\n }\n let cancelled = false;\n void loadGrammar(key)\n .then((grammar) => {\n if (!cancelled) view.current?.dispatch({ effects: language.reconfigure(grammar) });\n })\n .catch(() => {\n // A grammar is a separate chunk over the network, and the cockpit is\n // often read through a tunnel. Losing it costs syntax colour, not the\n // file, so fall back to plain text rather than failing the pane.\n if (!cancelled) view.current?.dispatch({ effects: language.reconfigure([]) });\n });\n return () => {\n cancelled = true;\n };\n }, [path]);\n\n return <div ref={host} data-testid={testId} className={cn('min-h-0 overflow-hidden', className)} />;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../icons/icons.cjs");const e=require("../lib/cn.cjs"),t=require("./Button.cjs");let n=require("radix-ui"),r=require("react/jsx-runtime"),i=require("class-variance-authority"),a=require("lucide-react");function o(e){return(0,r.jsx)(n.Dialog.Root,{"data-slot":`dialog`,...e})}function s(e){return(0,r.jsx)(n.Dialog.Trigger,{"data-slot":`dialog-trigger`,...e})}function c(e){return(0,r.jsx)(n.Dialog.Portal,{"data-slot":`dialog-portal`,...e})}function l(e){return(0,r.jsx)(n.Dialog.Close,{"data-slot":`dialog-close`,...e})}function u({className:t,...i}){return(0,r.jsx)(n.Dialog.Overlay,{"data-slot":`dialog-overlay`,className:e.cn(`fixed inset-0 z-40 bg-doom-deep/70 data-[state=open]:animate-doom-fade`,t),...i})}const d={sm:`w-[360px]`,md:`w-[480px]`,lg:`w-[620px]`};function f({className:t,children:i,width:a=`md`,...o}){return(0,r.jsxs)(c,{children:[(0,r.jsx)(u,{}),(0,r.jsx)(n.Dialog.Content,{"data-slot":`dialog-content`,className:e.cn(`fixed top-1/2 left-1/2 z-50 flex max-h-[
|
|
1
|
+
require("../icons/icons.cjs");const e=require("../lib/cn.cjs"),t=require("./Button.cjs");let n=require("radix-ui"),r=require("react/jsx-runtime"),i=require("class-variance-authority"),a=require("lucide-react");function o(e){return(0,r.jsx)(n.Dialog.Root,{"data-slot":`dialog`,...e})}function s(e){return(0,r.jsx)(n.Dialog.Trigger,{"data-slot":`dialog-trigger`,...e})}function c(e){return(0,r.jsx)(n.Dialog.Portal,{"data-slot":`dialog-portal`,...e})}function l(e){return(0,r.jsx)(n.Dialog.Close,{"data-slot":`dialog-close`,...e})}function u({className:t,...i}){return(0,r.jsx)(n.Dialog.Overlay,{"data-slot":`dialog-overlay`,className:e.cn(`fixed inset-0 z-40 bg-doom-deep/70 data-[state=open]:animate-doom-fade`,t),...i})}const d={sm:`w-[360px]`,md:`w-[480px]`,lg:`w-[620px]`};function f({className:t,children:i,width:a=`md`,...o}){return(0,r.jsxs)(c,{children:[(0,r.jsx)(u,{}),(0,r.jsx)(n.Dialog.Content,{"data-slot":`dialog-content`,className:e.cn(`fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-24px)] max-w-[calc(100vw-24px)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-pop`,d[a],t),...o,children:i})]})}function p({className:i,dismissible:o=!1,closeLabel:s=`close`,children:c,...l}){return(0,r.jsxs)(`div`,{"data-slot":`dialog-header`,className:e.cn(`flex min-w-0 items-center justify-between gap-3 border-b border-doom-border px-3 py-3 sm:px-4`,i),...l,children:[c,o?(0,r.jsx)(n.Dialog.Close,{asChild:!0,children:(0,r.jsx)(t.Button,{variant:`ghost`,size:`icon`,"aria-label":s,className:`text-doom-faint hover:text-doom-hi`,children:(0,r.jsx)(a.X,{className:`h-3 w-3`})})}):null]})}function m({className:t,...i}){return(0,r.jsx)(n.Dialog.Title,{"data-slot":`dialog-title`,className:e.cn(`text-[12px] font-bold tracking-wide text-doom-hi`,t),...i})}function h({className:t,...i}){return(0,r.jsx)(n.Dialog.Description,{"data-slot":`dialog-description`,className:e.cn(`text-[11px] leading-relaxed text-doom-dim`,t),...i})}function g({className:t,...n}){return(0,r.jsx)(`div`,{"data-slot":`dialog-body`,className:e.cn(`flex min-h-0 flex-col gap-3 overflow-y-auto px-3 py-3 sm:px-4 sm:py-4`,t),...n})}const _=(0,i.cva)(`flex shrink-0 items-center gap-2`,{variants:{variant:{plain:`justify-end`,bar:`min-h-[34px] flex-wrap justify-between border-t border-doom-border-soft bg-doom-deep px-3 py-1.5 sm:flex-nowrap sm:px-4 sm:py-0`}},defaultVariants:{variant:`plain`}});function v({className:t,variant:n,...i}){return(0,r.jsx)(`div`,{"data-slot":`dialog-footer`,className:e.cn(_({variant:n}),t),...i})}exports.Dialog=o,exports.DialogBody=g,exports.DialogClose=l,exports.DialogContent=f,exports.DialogDescription=h,exports.DialogFooter=v,exports.DialogHeader=p,exports.DialogOverlay=u,exports.DialogPortal=c,exports.DialogTitle=m,exports.DialogTrigger=s,exports.dialogFooterVariants=_;
|
|
2
2
|
//# sourceMappingURL=Dialog.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.cjs","names":["DialogPrimitive","cn","Button","CloseIcon","cva"],"sources":["../../../src/components/Dialog.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { Dialog as DialogPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\nimport { CloseIcon } from '../icons/icons.ts';\nimport { cn } from '../lib/cn.ts';\nimport { Button } from './Button.tsx';\n\n/**\n * shadcn's Dialog on Radix: focus trap, Escape, outside click, scroll lock,\n * and focus restored to the trigger on close. The frame is the Doom panel.\n */\nexport function Dialog(props: ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport function DialogTrigger(props: ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nexport function DialogPortal(props: ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nexport function DialogClose(props: ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nexport function DialogOverlay({ className, ...props }: ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn('fixed inset-0 z-40 bg-doom-deep/70 data-[state=open]:animate-doom-fade', className)}\n {...props}\n />\n );\n}\n\nexport interface DialogContentProps extends ComponentProps<typeof DialogPrimitive.Content> {\n /** Width preset; `className` may still override. */\n width?: 'sm' | 'md' | 'lg';\n}\n\nconst CONTENT_WIDTH = { sm: 'w-[360px]', md: 'w-[480px]', lg: 'w-[620px]' } as const;\n\nexport function DialogContent({ className, children, width = 'md', ...props }: DialogContentProps) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'fixed top-1/2 left-1/2 z-50 flex max-h-[
|
|
1
|
+
{"version":3,"file":"Dialog.cjs","names":["DialogPrimitive","cn","Button","CloseIcon","cva"],"sources":["../../../src/components/Dialog.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { Dialog as DialogPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\nimport { CloseIcon } from '../icons/icons.ts';\nimport { cn } from '../lib/cn.ts';\nimport { Button } from './Button.tsx';\n\n/**\n * shadcn's Dialog on Radix: focus trap, Escape, outside click, scroll lock,\n * and focus restored to the trigger on close. The frame is the Doom panel.\n */\nexport function Dialog(props: ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport function DialogTrigger(props: ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nexport function DialogPortal(props: ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nexport function DialogClose(props: ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nexport function DialogOverlay({ className, ...props }: ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn('fixed inset-0 z-40 bg-doom-deep/70 data-[state=open]:animate-doom-fade', className)}\n {...props}\n />\n );\n}\n\nexport interface DialogContentProps extends ComponentProps<typeof DialogPrimitive.Content> {\n /** Width preset; `className` may still override. */\n width?: 'sm' | 'md' | 'lg';\n}\n\nconst CONTENT_WIDTH = { sm: 'w-[360px]', md: 'w-[480px]', lg: 'w-[620px]' } as const;\n\nexport function DialogContent({ className, children, width = 'md', ...props }: DialogContentProps) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-24px)] max-w-[calc(100vw-24px)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-pop',\n CONTENT_WIDTH[width],\n className,\n )}\n {...props}\n >\n {children}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nexport interface DialogHeaderProps extends ComponentProps<'div'> {\n /**\n * Show the close control at the right of the strip. Off by default: most\n * headers already put something there (a spinner, a method label) and every\n * dialog closes on Escape, so an X that fights the existing content is worse\n * than none. Turn it on for a dialog whose only way out is the mouse.\n */\n dismissible?: boolean;\n /** What the close control announces. */\n closeLabel?: string;\n}\n\nexport function DialogHeader({\n className,\n dismissible = false,\n closeLabel = 'close',\n children,\n ...props\n}: DialogHeaderProps) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\n 'flex min-w-0 items-center justify-between gap-3 border-b border-doom-border px-3 py-3 sm:px-4',\n className,\n )}\n {...props}\n >\n {children}\n {dismissible ? (\n <DialogPrimitive.Close asChild>\n <Button variant=\"ghost\" size=\"icon\" aria-label={closeLabel} className=\"text-doom-faint hover:text-doom-hi\">\n <CloseIcon className=\"h-3 w-3\" />\n </Button>\n </DialogPrimitive.Close>\n ) : null}\n </div>\n );\n}\n\nexport function DialogTitle({ className, ...props }: ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn('text-[12px] font-bold tracking-wide text-doom-hi', className)}\n {...props}\n />\n );\n}\n\nexport function DialogDescription({ className, ...props }: ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn('text-[11px] leading-relaxed text-doom-dim', className)}\n {...props}\n />\n );\n}\n\nexport function DialogBody({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"dialog-body\"\n className={cn('flex min-h-0 flex-col gap-3 overflow-y-auto px-3 py-3 sm:px-4 sm:py-4', className)}\n {...props}\n />\n );\n}\n\nexport const dialogFooterVariants = cva('flex shrink-0 items-center gap-2', {\n variants: {\n variant: {\n /** Buttons alone, sitting inside the body's padding. */\n plain: 'justify-end',\n /**\n * The full-width strip: a hint on the left, the buttons on the right,\n * recessed and ruled off from the body. The same shape PopoverFooter\n * draws, because a dialog and a popover promise their keys the same way.\n */\n bar: 'min-h-[34px] flex-wrap justify-between border-t border-doom-border-soft bg-doom-deep px-3 py-1.5 sm:flex-nowrap sm:px-4 sm:py-0',\n },\n },\n defaultVariants: { variant: 'plain' },\n});\n\nexport interface DialogFooterProps extends ComponentProps<'div'>, VariantProps<typeof dialogFooterVariants> {}\n\nexport function DialogFooter({ className, variant, ...props }: DialogFooterProps) {\n return <div data-slot=\"dialog-footer\" className={cn(dialogFooterVariants({ variant }), className)} {...props} />;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.d.mts","names":[],"sources":["../../../src/components/Dialog.tsx"],"mappings":";;;;;;;;iBAWgB,SAAO,OAAO,sBAAsB,OAAgB,oCAAK,IAAA;iBAIzD,cAAc,OAAO,sBAAsB,OAAgB,uCAAQ,IAAA;iBAQnE,YAAY,OAAO,sBAAsB,OAAgB,qCAAM,IAAA;UAc9D,2BAA2B,sBAAsB,OAAgB;;EAEhF;;iBAKc,gBAAgB,WAAW,UAAU,UAAiB,SAAS,iDAAkB,IAAA;UAmBhF,0BAA0B;;;;;;;EAOzC;;EAEA;;iBAGc,eACd,WACA,aACA,YACA,aACG,SACF,gDAAiB,IAAA;
|
|
1
|
+
{"version":3,"file":"Dialog.d.mts","names":[],"sources":["../../../src/components/Dialog.tsx"],"mappings":";;;;;;;;iBAWgB,SAAO,OAAO,sBAAsB,OAAgB,oCAAK,IAAA;iBAIzD,cAAc,OAAO,sBAAsB,OAAgB,uCAAQ,IAAA;iBAQnE,YAAY,OAAO,sBAAsB,OAAgB,qCAAM,IAAA;UAc9D,2BAA2B,sBAAsB,OAAgB;;EAEhF;;iBAKc,gBAAgB,WAAW,UAAU,UAAiB,SAAS,iDAAkB,IAAA;UAmBhF,0BAA0B;;;;;;;EAOzC;;EAEA;;iBAGc,eACd,WACA,aACA,YACA,aACG,SACF,gDAAiB,IAAA;iBAsBJ,cAAc,cAAc,SAAS,sBAAsB,OAAgB,qCAAM,IAAA;iBAUjF,oBAAoB,cAAc,SAAS,sBAAsB,OAAgB,2CAAY,IAAA;iBAU7F,aAAa,cAAc,SAAS,oDAAqB,IAAA;cAU5D,uBAAoB;;6CAc/B;UAEe,0BAA0B,uBAAuB,oBAAoB;iBAEtE,eAAe,WAAW,YAAY,SAAS,gDAAiB,IAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{CloseIcon as e}from"../icons/icons.mjs";import{cn as t}from"../lib/cn.mjs";import{Button as n}from"./Button.mjs";import{Dialog as r}from"radix-ui";import{jsx as i,jsxs as a}from"react/jsx-runtime";import{cva as o}from"class-variance-authority";function s(e){return i(r.Root,{"data-slot":`dialog`,...e})}function c(e){return i(r.Trigger,{"data-slot":`dialog-trigger`,...e})}function l(e){return i(r.Portal,{"data-slot":`dialog-portal`,...e})}function u(e){return i(r.Close,{"data-slot":`dialog-close`,...e})}function d({className:e,...n}){return i(r.Overlay,{"data-slot":`dialog-overlay`,className:t(`fixed inset-0 z-40 bg-doom-deep/70 data-[state=open]:animate-doom-fade`,e),...n})}const f={sm:`w-[360px]`,md:`w-[480px]`,lg:`w-[620px]`};function p({className:e,children:n,width:o=`md`,...s}){return a(l,{children:[i(d,{}),i(r.Content,{"data-slot":`dialog-content`,className:t(`fixed top-1/2 left-1/2 z-50 flex max-h-[
|
|
1
|
+
import{CloseIcon as e}from"../icons/icons.mjs";import{cn as t}from"../lib/cn.mjs";import{Button as n}from"./Button.mjs";import{Dialog as r}from"radix-ui";import{jsx as i,jsxs as a}from"react/jsx-runtime";import{cva as o}from"class-variance-authority";function s(e){return i(r.Root,{"data-slot":`dialog`,...e})}function c(e){return i(r.Trigger,{"data-slot":`dialog-trigger`,...e})}function l(e){return i(r.Portal,{"data-slot":`dialog-portal`,...e})}function u(e){return i(r.Close,{"data-slot":`dialog-close`,...e})}function d({className:e,...n}){return i(r.Overlay,{"data-slot":`dialog-overlay`,className:t(`fixed inset-0 z-40 bg-doom-deep/70 data-[state=open]:animate-doom-fade`,e),...n})}const f={sm:`w-[360px]`,md:`w-[480px]`,lg:`w-[620px]`};function p({className:e,children:n,width:o=`md`,...s}){return a(l,{children:[i(d,{}),i(r.Content,{"data-slot":`dialog-content`,className:t(`fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-24px)] max-w-[calc(100vw-24px)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-pop`,f[o],e),...s,children:n})]})}function m({className:o,dismissible:s=!1,closeLabel:c=`close`,children:l,...u}){return a(`div`,{"data-slot":`dialog-header`,className:t(`flex min-w-0 items-center justify-between gap-3 border-b border-doom-border px-3 py-3 sm:px-4`,o),...u,children:[l,s?i(r.Close,{asChild:!0,children:i(n,{variant:`ghost`,size:`icon`,"aria-label":c,className:`text-doom-faint hover:text-doom-hi`,children:i(e,{className:`h-3 w-3`})})}):null]})}function h({className:e,...n}){return i(r.Title,{"data-slot":`dialog-title`,className:t(`text-[12px] font-bold tracking-wide text-doom-hi`,e),...n})}function g({className:e,...n}){return i(r.Description,{"data-slot":`dialog-description`,className:t(`text-[11px] leading-relaxed text-doom-dim`,e),...n})}function _({className:e,...n}){return i(`div`,{"data-slot":`dialog-body`,className:t(`flex min-h-0 flex-col gap-3 overflow-y-auto px-3 py-3 sm:px-4 sm:py-4`,e),...n})}const v=o(`flex shrink-0 items-center gap-2`,{variants:{variant:{plain:`justify-end`,bar:`min-h-[34px] flex-wrap justify-between border-t border-doom-border-soft bg-doom-deep px-3 py-1.5 sm:flex-nowrap sm:px-4 sm:py-0`}},defaultVariants:{variant:`plain`}});function y({className:e,variant:n,...r}){return i(`div`,{"data-slot":`dialog-footer`,className:t(v({variant:n}),e),...r})}export{s as Dialog,_ as DialogBody,u as DialogClose,p as DialogContent,g as DialogDescription,y as DialogFooter,m as DialogHeader,d as DialogOverlay,l as DialogPortal,h as DialogTitle,c as DialogTrigger,v as dialogFooterVariants};
|
|
2
2
|
//# sourceMappingURL=Dialog.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.mjs","names":["Dialog","DialogPrimitive"],"sources":["../../../src/components/Dialog.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { Dialog as DialogPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\nimport { CloseIcon } from '../icons/icons.ts';\nimport { cn } from '../lib/cn.ts';\nimport { Button } from './Button.tsx';\n\n/**\n * shadcn's Dialog on Radix: focus trap, Escape, outside click, scroll lock,\n * and focus restored to the trigger on close. The frame is the Doom panel.\n */\nexport function Dialog(props: ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport function DialogTrigger(props: ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nexport function DialogPortal(props: ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nexport function DialogClose(props: ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nexport function DialogOverlay({ className, ...props }: ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn('fixed inset-0 z-40 bg-doom-deep/70 data-[state=open]:animate-doom-fade', className)}\n {...props}\n />\n );\n}\n\nexport interface DialogContentProps extends ComponentProps<typeof DialogPrimitive.Content> {\n /** Width preset; `className` may still override. */\n width?: 'sm' | 'md' | 'lg';\n}\n\nconst CONTENT_WIDTH = { sm: 'w-[360px]', md: 'w-[480px]', lg: 'w-[620px]' } as const;\n\nexport function DialogContent({ className, children, width = 'md', ...props }: DialogContentProps) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'fixed top-1/2 left-1/2 z-50 flex max-h-[
|
|
1
|
+
{"version":3,"file":"Dialog.mjs","names":["Dialog","DialogPrimitive"],"sources":["../../../src/components/Dialog.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { Dialog as DialogPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\nimport { CloseIcon } from '../icons/icons.ts';\nimport { cn } from '../lib/cn.ts';\nimport { Button } from './Button.tsx';\n\n/**\n * shadcn's Dialog on Radix: focus trap, Escape, outside click, scroll lock,\n * and focus restored to the trigger on close. The frame is the Doom panel.\n */\nexport function Dialog(props: ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport function DialogTrigger(props: ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nexport function DialogPortal(props: ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nexport function DialogClose(props: ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nexport function DialogOverlay({ className, ...props }: ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn('fixed inset-0 z-40 bg-doom-deep/70 data-[state=open]:animate-doom-fade', className)}\n {...props}\n />\n );\n}\n\nexport interface DialogContentProps extends ComponentProps<typeof DialogPrimitive.Content> {\n /** Width preset; `className` may still override. */\n width?: 'sm' | 'md' | 'lg';\n}\n\nconst CONTENT_WIDTH = { sm: 'w-[360px]', md: 'w-[480px]', lg: 'w-[620px]' } as const;\n\nexport function DialogContent({ className, children, width = 'md', ...props }: DialogContentProps) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-24px)] max-w-[calc(100vw-24px)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-pop',\n CONTENT_WIDTH[width],\n className,\n )}\n {...props}\n >\n {children}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nexport interface DialogHeaderProps extends ComponentProps<'div'> {\n /**\n * Show the close control at the right of the strip. Off by default: most\n * headers already put something there (a spinner, a method label) and every\n * dialog closes on Escape, so an X that fights the existing content is worse\n * than none. Turn it on for a dialog whose only way out is the mouse.\n */\n dismissible?: boolean;\n /** What the close control announces. */\n closeLabel?: string;\n}\n\nexport function DialogHeader({\n className,\n dismissible = false,\n closeLabel = 'close',\n children,\n ...props\n}: DialogHeaderProps) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\n 'flex min-w-0 items-center justify-between gap-3 border-b border-doom-border px-3 py-3 sm:px-4',\n className,\n )}\n {...props}\n >\n {children}\n {dismissible ? (\n <DialogPrimitive.Close asChild>\n <Button variant=\"ghost\" size=\"icon\" aria-label={closeLabel} className=\"text-doom-faint hover:text-doom-hi\">\n <CloseIcon className=\"h-3 w-3\" />\n </Button>\n </DialogPrimitive.Close>\n ) : null}\n </div>\n );\n}\n\nexport function DialogTitle({ className, ...props }: ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn('text-[12px] font-bold tracking-wide text-doom-hi', className)}\n {...props}\n />\n );\n}\n\nexport function DialogDescription({ className, ...props }: ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn('text-[11px] leading-relaxed text-doom-dim', className)}\n {...props}\n />\n );\n}\n\nexport function DialogBody({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"dialog-body\"\n className={cn('flex min-h-0 flex-col gap-3 overflow-y-auto px-3 py-3 sm:px-4 sm:py-4', className)}\n {...props}\n />\n );\n}\n\nexport const dialogFooterVariants = cva('flex shrink-0 items-center gap-2', {\n variants: {\n variant: {\n /** Buttons alone, sitting inside the body's padding. */\n plain: 'justify-end',\n /**\n * The full-width strip: a hint on the left, the buttons on the right,\n * recessed and ruled off from the body. The same shape PopoverFooter\n * draws, because a dialog and a popover promise their keys the same way.\n */\n bar: 'min-h-[34px] flex-wrap justify-between border-t border-doom-border-soft bg-doom-deep px-3 py-1.5 sm:flex-nowrap sm:px-4 sm:py-0',\n },\n },\n defaultVariants: { variant: 'plain' },\n});\n\nexport interface DialogFooterProps extends ComponentProps<'div'>, VariantProps<typeof dialogFooterVariants> {}\n\nexport function DialogFooter({ className, variant, ...props }: DialogFooterProps) {\n return <div data-slot=\"dialog-footer\" className={cn(dialogFooterVariants({ variant }), className)} {...props} />;\n}\n"],"mappings":"2PAWA,SAAgBA,EAAO,EAAoD,CACzE,OAAO,EAACC,EAAgB,KAAjB,CAAsB,YAAU,SAAS,GAAI,CAAQ,CAAA,CAC9D,CAEA,SAAgB,EAAc,EAAuD,CACnF,OAAO,EAACA,EAAgB,QAAjB,CAAyB,YAAU,iBAAiB,GAAI,CAAQ,CAAA,CACzE,CAEA,SAAgB,EAAa,EAAsD,CACjF,OAAO,EAACA,EAAgB,OAAjB,CAAwB,YAAU,gBAAgB,GAAI,CAAQ,CAAA,CACvE,CAEA,SAAgB,EAAY,EAAqD,CAC/E,OAAO,EAACA,EAAgB,MAAjB,CAAuB,YAAU,eAAe,GAAI,CAAQ,CAAA,CACrE,CAEA,SAAgB,EAAc,CAAE,YAAW,GAAG,GAAyD,CACrG,OACE,EAACA,EAAgB,QAAjB,CACE,YAAU,iBACV,UAAW,EAAG,yEAA0E,CAAS,EACjG,GAAI,CACL,CAAA,CAEL,CAOA,MAAM,EAAgB,CAAE,GAAI,YAAa,GAAI,YAAa,GAAI,WAAY,EAE1E,SAAgB,EAAc,CAAE,YAAW,WAAU,QAAQ,KAAM,GAAG,GAA6B,CACjG,OACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAgB,CAAA,EAChB,EAACA,EAAgB,QAAjB,CACE,YAAU,iBACV,UAAW,EACT,yQACA,EAAc,GACd,CACF,EACA,GAAI,EAEH,UACsB,CAAA,CACb,CAAA,CAAA,CAElB,CAcA,SAAgB,EAAa,CAC3B,YACA,cAAc,GACd,aAAa,QACb,WACA,GAAG,GACiB,CACpB,OACE,EAAC,MAAD,CACE,YAAU,gBACV,UAAW,EACT,gGACA,CACF,EACA,GAAI,EANN,SAAA,CAQG,EACA,EACC,EAACA,EAAgB,MAAjB,CAAuB,QAAA,GACrB,SAAA,EAAC,EAAD,CAAQ,QAAQ,QAAQ,KAAK,OAAO,aAAY,EAAY,UAAU,qCACpE,SAAA,EAAC,EAAD,CAAW,UAAU,SAAW,CAAA,CAC1B,CAAA,CACa,CAAA,EACrB,IACD,GAET,CAEA,SAAgB,EAAY,CAAE,YAAW,GAAG,GAAuD,CACjG,OACE,EAACA,EAAgB,MAAjB,CACE,YAAU,eACV,UAAW,EAAG,mDAAoD,CAAS,EAC3E,GAAI,CACL,CAAA,CAEL,CAEA,SAAgB,EAAkB,CAAE,YAAW,GAAG,GAA6D,CAC7G,OACE,EAACA,EAAgB,YAAjB,CACE,YAAU,qBACV,UAAW,EAAG,4CAA6C,CAAS,EACpE,GAAI,CACL,CAAA,CAEL,CAEA,SAAgB,EAAW,CAAE,YAAW,GAAG,GAAgC,CACzE,OACE,EAAC,MAAD,CACE,YAAU,cACV,UAAW,EAAG,wEAAyE,CAAS,EAChG,GAAI,CACL,CAAA,CAEL,CAEA,MAAa,EAAuB,EAAI,mCAAoC,CAC1E,SAAU,CACR,QAAS,CAEP,MAAO,cAMP,IAAK,iIACP,CACF,EACA,gBAAiB,CAAE,QAAS,OAAQ,CACtC,CAAC,EAID,SAAgB,EAAa,CAAE,YAAW,UAAS,GAAG,GAA4B,CAChF,OAAO,EAAC,MAAD,CAAK,YAAU,gBAAgB,UAAW,EAAG,EAAqB,CAAE,SAAQ,CAAC,EAAG,CAAS,EAAG,GAAI,CAAQ,CAAA,CACjH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../lib/cn.cjs");let t=require("radix-ui"),n=require("react/jsx-runtime");function r({title:r,description:i,children:a,className:o,asChild:s=!1,...c}){let l=s?t.Slot.Root:`div`;return(0,n.jsx)(l,{"data-slot":`empty-state`,className:e.cn(`flex flex-1 items-center justify-center`,o),...c,children:(0,n.jsxs)(`div`,{className:`flex w-[520px] max-w-full flex-col items-center gap-3 text-center`,children:[(0,n.jsx)(`span`,{className:`text-[14px] font-bold text-doom-hi`,children:r}),i?(0,n.jsx)(`span`,{className:`text-[11px] leading-relaxed text-doom-dim`,children:i}):null,a]})})}exports.EmptyState=r;
|
|
1
|
+
const e=require("../lib/cn.cjs");let t=require("radix-ui"),n=require("react/jsx-runtime");function r({title:r,description:i,children:a,className:o,asChild:s=!1,...c}){let l=s?t.Slot.Root:`div`;return(0,n.jsx)(l,{"data-slot":`empty-state`,className:e.cn(`flex flex-1 items-center justify-center px-3 py-4 sm:px-4`,o),...c,children:(0,n.jsxs)(`div`,{className:`flex w-[520px] max-w-full flex-col items-center gap-3 text-center`,children:[(0,n.jsx)(`span`,{className:`text-[14px] font-bold text-doom-hi`,children:r}),i?(0,n.jsx)(`span`,{className:`text-[11px] leading-relaxed text-doom-dim`,children:i}):null,a]})})}exports.EmptyState=r;
|
|
2
2
|
//# sourceMappingURL=EmptyState.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.cjs","names":["Slot","cn"],"sources":["../../../src/components/EmptyState.tsx"],"sourcesContent":["import { Slot } from 'radix-ui';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { cn } from '../lib/cn.ts';\n\nexport interface EmptyStateProps extends Omit<ComponentProps<'div'>, 'title'> {\n title: ReactNode;\n description?: ReactNode;\n /** Optional calls to action under the copy. */\n children?: ReactNode;\n /**\n * Render the child element instead of a <div>, so an empty row inside a\n * list stays an <li> and the list keeps its semantics.\n */\n asChild?: boolean;\n}\n\n/** The centred \"nothing here yet\" card every empty panel shares. */\nexport function EmptyState({ title, description, children, className, asChild = false, ...props }: EmptyStateProps) {\n const Component = asChild ? Slot.Root : 'div';\n return (\n <Component
|
|
1
|
+
{"version":3,"file":"EmptyState.cjs","names":["Slot","cn"],"sources":["../../../src/components/EmptyState.tsx"],"sourcesContent":["import { Slot } from 'radix-ui';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { cn } from '../lib/cn.ts';\n\nexport interface EmptyStateProps extends Omit<ComponentProps<'div'>, 'title'> {\n title: ReactNode;\n description?: ReactNode;\n /** Optional calls to action under the copy. */\n children?: ReactNode;\n /**\n * Render the child element instead of a <div>, so an empty row inside a\n * list stays an <li> and the list keeps its semantics.\n */\n asChild?: boolean;\n}\n\n/** The centred \"nothing here yet\" card every empty panel shares. */\nexport function EmptyState({ title, description, children, className, asChild = false, ...props }: EmptyStateProps) {\n const Component = asChild ? Slot.Root : 'div';\n return (\n <Component\n data-slot=\"empty-state\"\n className={cn('flex flex-1 items-center justify-center px-3 py-4 sm:px-4', className)}\n {...props}\n >\n <div className=\"flex w-[520px] max-w-full flex-col items-center gap-3 text-center\">\n <span className=\"text-[14px] font-bold text-doom-hi\">{title}</span>\n {description ? <span className=\"text-[11px] leading-relaxed text-doom-dim\">{description}</span> : null}\n {children}\n </div>\n </Component>\n );\n}\n"],"mappings":"0FAiBA,SAAgB,EAAW,CAAE,QAAO,cAAa,WAAU,YAAW,UAAU,GAAO,GAAG,GAA0B,CAClH,IAAM,EAAY,EAAUA,EAAAA,KAAK,KAAO,MACxC,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,YAAU,cACV,UAAWC,EAAAA,GAAG,4DAA6D,CAAS,EACpF,GAAI,EAEJ,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,oEAAf,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,qCAAsC,SAAA,CAAY,CAAA,EACjE,GAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,4CAA6C,SAAA,CAAkB,CAAA,EAAI,KACjG,CACE,GACI,CAAA,CAEf"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{cn as e}from"../lib/cn.mjs";import{Slot as t}from"radix-ui";import{jsx as n,jsxs as r}from"react/jsx-runtime";function i({title:i,description:a,children:o,className:s,asChild:c=!1,...l}){let u=c?t.Root:`div`;return n(u,{"data-slot":`empty-state`,className:e(`flex flex-1 items-center justify-center`,s),...l,children:r(`div`,{className:`flex w-[520px] max-w-full flex-col items-center gap-3 text-center`,children:[n(`span`,{className:`text-[14px] font-bold text-doom-hi`,children:i}),a?n(`span`,{className:`text-[11px] leading-relaxed text-doom-dim`,children:a}):null,o]})})}export{i as EmptyState};
|
|
1
|
+
import{cn as e}from"../lib/cn.mjs";import{Slot as t}from"radix-ui";import{jsx as n,jsxs as r}from"react/jsx-runtime";function i({title:i,description:a,children:o,className:s,asChild:c=!1,...l}){let u=c?t.Root:`div`;return n(u,{"data-slot":`empty-state`,className:e(`flex flex-1 items-center justify-center px-3 py-4 sm:px-4`,s),...l,children:r(`div`,{className:`flex w-[520px] max-w-full flex-col items-center gap-3 text-center`,children:[n(`span`,{className:`text-[14px] font-bold text-doom-hi`,children:i}),a?n(`span`,{className:`text-[11px] leading-relaxed text-doom-dim`,children:a}):null,o]})})}export{i as EmptyState};
|
|
2
2
|
//# sourceMappingURL=EmptyState.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.mjs","names":[],"sources":["../../../src/components/EmptyState.tsx"],"sourcesContent":["import { Slot } from 'radix-ui';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { cn } from '../lib/cn.ts';\n\nexport interface EmptyStateProps extends Omit<ComponentProps<'div'>, 'title'> {\n title: ReactNode;\n description?: ReactNode;\n /** Optional calls to action under the copy. */\n children?: ReactNode;\n /**\n * Render the child element instead of a <div>, so an empty row inside a\n * list stays an <li> and the list keeps its semantics.\n */\n asChild?: boolean;\n}\n\n/** The centred \"nothing here yet\" card every empty panel shares. */\nexport function EmptyState({ title, description, children, className, asChild = false, ...props }: EmptyStateProps) {\n const Component = asChild ? Slot.Root : 'div';\n return (\n <Component
|
|
1
|
+
{"version":3,"file":"EmptyState.mjs","names":[],"sources":["../../../src/components/EmptyState.tsx"],"sourcesContent":["import { Slot } from 'radix-ui';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { cn } from '../lib/cn.ts';\n\nexport interface EmptyStateProps extends Omit<ComponentProps<'div'>, 'title'> {\n title: ReactNode;\n description?: ReactNode;\n /** Optional calls to action under the copy. */\n children?: ReactNode;\n /**\n * Render the child element instead of a <div>, so an empty row inside a\n * list stays an <li> and the list keeps its semantics.\n */\n asChild?: boolean;\n}\n\n/** The centred \"nothing here yet\" card every empty panel shares. */\nexport function EmptyState({ title, description, children, className, asChild = false, ...props }: EmptyStateProps) {\n const Component = asChild ? Slot.Root : 'div';\n return (\n <Component\n data-slot=\"empty-state\"\n className={cn('flex flex-1 items-center justify-center px-3 py-4 sm:px-4', className)}\n {...props}\n >\n <div className=\"flex w-[520px] max-w-full flex-col items-center gap-3 text-center\">\n <span className=\"text-[14px] font-bold text-doom-hi\">{title}</span>\n {description ? <span className=\"text-[11px] leading-relaxed text-doom-dim\">{description}</span> : null}\n {children}\n </div>\n </Component>\n );\n}\n"],"mappings":"qHAiBA,SAAgB,EAAW,CAAE,QAAO,cAAa,WAAU,YAAW,UAAU,GAAO,GAAG,GAA0B,CAClH,IAAM,EAAY,EAAU,EAAK,KAAO,MACxC,OACE,EAAC,EAAD,CACE,YAAU,cACV,UAAW,EAAG,4DAA6D,CAAS,EACpF,GAAI,EAEJ,SAAA,EAAC,MAAD,CAAK,UAAU,oEAAf,SAAA,CACE,EAAC,OAAD,CAAM,UAAU,qCAAsC,SAAA,CAAY,CAAA,EACjE,EAAc,EAAC,OAAD,CAAM,UAAU,4CAA6C,SAAA,CAAkB,CAAA,EAAI,KACjG,CACE,GACI,CAAA,CAEf"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require("../icons/icons.cjs");const e=require("../lib/cn.cjs"),t=require("./Badge.cjs"),n=require("../lib/media.cjs");let r=require("react/jsx-runtime"),i=require("lucide-react");const a=`max-w-full rounded border border-doom-border bg-doom-deep`;function o({src:o,path:s,kind:c,className:l,"data-testid":u}){let d=c??n.mediaKindOf(s),f=s.split(`/`).at(-1)??s;return d===`image`?(0,r.jsx)(`a`,{href:o,target:`_blank`,rel:`noreferrer`,"data-testid":u,"data-kind":d,children:(0,r.jsx)(`img`,{src:o,alt:s,className:e.cn(a,`max-h-[36rem]`,l)})}):d===`video`?(0,r.jsx)(`video`,{src:o,controls:!0,preload:`metadata`,"data-testid":u,"data-kind":d,className:e.cn(a,`max-h-[36rem]`,l)}):d===`pdf`?(0,r.jsx)(`iframe`,{src:o,title:s,"data-testid":u,"data-kind":d,className:e.cn(a,`h-[36rem] w-full`,l)}):(0,r.jsx)(t.Badge,{asChild:!0,size:`md`,"data-testid":u,"data-kind":d,className:e.cn(`self-start bg-doom-panel text-doom-text hover:border-doom-blue/50`,l),children:(0,r.jsxs)(`a`,{href:o,download:f,children:[(0,r.jsx)(i.FileText,{className:`h-3 w-3 shrink-0 text-doom-faint`}),`download `,f]})})}exports.MediaPreview=o;
|
|
2
|
+
//# sourceMappingURL=MediaPreview.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaPreview.cjs","names":["mediaKindOf","cn","Badge","FileIcon"],"sources":["../../../src/components/MediaPreview.tsx"],"sourcesContent":["import { FileIcon } from '../icons/icons.ts';\nimport { cn } from '../lib/cn.ts';\nimport { mediaKindOf } from '../lib/media.ts';\nimport type { MediaKind } from '../types/editor.ts';\nimport { Badge } from './Badge.tsx';\n\n/**\n * A file the browser can show but not edit.\n *\n * It renders bytes a server is already serving, so the caller supplies the\n * URL and this decides only which element reads it. Everything the browser\n * cannot render is a download rather than a converted approximation: a `.docx`\n * turned into HTML is a different document, and offering to edit that one\n * would be offering to overwrite the real one with it.\n */\n\nexport interface MediaPreviewProps {\n /** Where the bytes are served from. */\n src: string;\n /** The file's path, used for the accessible name and the download name. */\n path: string;\n /** Overrides the kind inferred from the path, for a server that knows better. */\n kind?: MediaKind;\n className?: string;\n 'data-testid'?: string;\n}\n\nconst FRAME = 'max-w-full rounded border border-doom-border bg-doom-deep';\n\nexport function MediaPreview({ src, path, kind, className, 'data-testid': testId }: MediaPreviewProps) {\n const resolved = kind ?? mediaKindOf(path);\n const name = path.split('/').at(-1) ?? path;\n\n if (resolved === 'image') {\n return (\n <a href={src} target=\"_blank\" rel=\"noreferrer\" data-testid={testId} data-kind={resolved}>\n <img src={src} alt={path} className={cn(FRAME, 'max-h-[36rem]', className)} />\n </a>\n );\n }\n if (resolved === 'video') {\n return (\n <video\n src={src}\n controls\n preload=\"metadata\"\n data-testid={testId}\n data-kind={resolved}\n className={cn(FRAME, 'max-h-[36rem]', className)}\n />\n );\n }\n if (resolved === 'pdf') {\n return (\n <iframe\n src={src}\n title={path}\n data-testid={testId}\n data-kind={resolved}\n className={cn(FRAME, 'h-[36rem] w-full', className)}\n />\n );\n }\n return (\n <Badge\n asChild\n size=\"md\"\n data-testid={testId}\n data-kind={resolved}\n className={cn('self-start bg-doom-panel text-doom-text hover:border-doom-blue/50', className)}\n >\n <a href={src} download={name}>\n <FileIcon className=\"h-3 w-3 shrink-0 text-doom-faint\" />\n download {name}\n </a>\n </Badge>\n );\n}\n"],"mappings":"mLA2BA,MAAM,EAAQ,4DAEd,SAAgB,EAAa,CAAE,MAAK,OAAM,OAAM,YAAW,cAAe,GAA6B,CACrG,IAAM,EAAW,GAAQA,EAAAA,YAAY,CAAI,EACnC,EAAO,EAAK,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAK,EAgCvC,OA9BI,IAAa,SAEb,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,KAAM,EAAK,OAAO,SAAS,IAAI,aAAa,cAAa,EAAQ,YAAW,EAC7E,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAU,MAAK,IAAK,EAAM,UAAWC,EAAAA,GAAG,EAAO,gBAAiB,CAAS,CAAI,CAAA,CAC5E,CAAA,EAGH,IAAa,SAEb,EAAA,EAAA,IAAA,CAAC,QAAD,CACO,MACL,SAAA,GACA,QAAQ,WACR,cAAa,EACb,YAAW,EACX,UAAWA,EAAAA,GAAG,EAAO,gBAAiB,CAAS,CAChD,CAAA,EAGD,IAAa,OAEb,EAAA,EAAA,IAAA,CAAC,SAAD,CACO,MACL,MAAO,EACP,cAAa,EACb,YAAW,EACX,UAAWA,EAAAA,GAAG,EAAO,mBAAoB,CAAS,CACnD,CAAA,GAIH,EAAA,EAAA,IAAA,CAACC,EAAAA,MAAD,CACE,QAAA,GACA,KAAK,KACL,cAAa,EACb,YAAW,EACX,UAAWD,EAAAA,GAAG,oEAAqE,CAAS,EAE5F,UAAA,EAAA,EAAA,KAAA,CAAC,IAAD,CAAG,KAAM,EAAK,SAAU,EAAxB,SAAA,EACE,EAAA,EAAA,IAAA,CAACE,EAAAA,SAAD,CAAU,UAAU,kCAAoC,CAAA,EAAC,YAC/C,CACT,GACE,CAAA,CAEX"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MediaKind } from "../types/editor.mjs";
|
|
2
|
+
//#region src/components/MediaPreview.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* A file the browser can show but not edit.
|
|
5
|
+
*
|
|
6
|
+
* It renders bytes a server is already serving, so the caller supplies the
|
|
7
|
+
* URL and this decides only which element reads it. Everything the browser
|
|
8
|
+
* cannot render is a download rather than a converted approximation: a `.docx`
|
|
9
|
+
* turned into HTML is a different document, and offering to edit that one
|
|
10
|
+
* would be offering to overwrite the real one with it.
|
|
11
|
+
*/
|
|
12
|
+
interface MediaPreviewProps {
|
|
13
|
+
/** Where the bytes are served from. */
|
|
14
|
+
src: string;
|
|
15
|
+
/** The file's path, used for the accessible name and the download name. */
|
|
16
|
+
path: string;
|
|
17
|
+
/** Overrides the kind inferred from the path, for a server that knows better. */
|
|
18
|
+
kind?: MediaKind;
|
|
19
|
+
className?: string;
|
|
20
|
+
'data-testid'?: string;
|
|
21
|
+
}
|
|
22
|
+
declare function MediaPreview({ src, path, kind, className, 'data-testid': testId }: MediaPreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { MediaPreview, MediaPreviewProps };
|
|
25
|
+
//# sourceMappingURL=MediaPreview.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaPreview.d.mts","names":[],"sources":["../../../src/components/MediaPreview.tsx"],"mappings":";;;;;;;;;;;UAgBiB;;EAEf;;EAEA;;EAEA,OAAO;EACP;EACA;;iBAKc,eAAe,KAAK,MAAM,MAAM,0BAA0B,UAAU,gDAAiB,IAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{FileIcon as e}from"../icons/icons.mjs";import{cn as t}from"../lib/cn.mjs";import{Badge as n}from"./Badge.mjs";import{mediaKindOf as r}from"../lib/media.mjs";import{jsx as i,jsxs as a}from"react/jsx-runtime";const o=`max-w-full rounded border border-doom-border bg-doom-deep`;function s({src:s,path:c,kind:l,className:u,"data-testid":d}){let f=l??r(c),p=c.split(`/`).at(-1)??c;return f===`image`?i(`a`,{href:s,target:`_blank`,rel:`noreferrer`,"data-testid":d,"data-kind":f,children:i(`img`,{src:s,alt:c,className:t(o,`max-h-[36rem]`,u)})}):f===`video`?i(`video`,{src:s,controls:!0,preload:`metadata`,"data-testid":d,"data-kind":f,className:t(o,`max-h-[36rem]`,u)}):f===`pdf`?i(`iframe`,{src:s,title:c,"data-testid":d,"data-kind":f,className:t(o,`h-[36rem] w-full`,u)}):i(n,{asChild:!0,size:`md`,"data-testid":d,"data-kind":f,className:t(`self-start bg-doom-panel text-doom-text hover:border-doom-blue/50`,u),children:a(`a`,{href:s,download:p,children:[i(e,{className:`h-3 w-3 shrink-0 text-doom-faint`}),`download `,p]})})}export{s as MediaPreview};
|
|
2
|
+
//# sourceMappingURL=MediaPreview.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaPreview.mjs","names":[],"sources":["../../../src/components/MediaPreview.tsx"],"sourcesContent":["import { FileIcon } from '../icons/icons.ts';\nimport { cn } from '../lib/cn.ts';\nimport { mediaKindOf } from '../lib/media.ts';\nimport type { MediaKind } from '../types/editor.ts';\nimport { Badge } from './Badge.tsx';\n\n/**\n * A file the browser can show but not edit.\n *\n * It renders bytes a server is already serving, so the caller supplies the\n * URL and this decides only which element reads it. Everything the browser\n * cannot render is a download rather than a converted approximation: a `.docx`\n * turned into HTML is a different document, and offering to edit that one\n * would be offering to overwrite the real one with it.\n */\n\nexport interface MediaPreviewProps {\n /** Where the bytes are served from. */\n src: string;\n /** The file's path, used for the accessible name and the download name. */\n path: string;\n /** Overrides the kind inferred from the path, for a server that knows better. */\n kind?: MediaKind;\n className?: string;\n 'data-testid'?: string;\n}\n\nconst FRAME = 'max-w-full rounded border border-doom-border bg-doom-deep';\n\nexport function MediaPreview({ src, path, kind, className, 'data-testid': testId }: MediaPreviewProps) {\n const resolved = kind ?? mediaKindOf(path);\n const name = path.split('/').at(-1) ?? path;\n\n if (resolved === 'image') {\n return (\n <a href={src} target=\"_blank\" rel=\"noreferrer\" data-testid={testId} data-kind={resolved}>\n <img src={src} alt={path} className={cn(FRAME, 'max-h-[36rem]', className)} />\n </a>\n );\n }\n if (resolved === 'video') {\n return (\n <video\n src={src}\n controls\n preload=\"metadata\"\n data-testid={testId}\n data-kind={resolved}\n className={cn(FRAME, 'max-h-[36rem]', className)}\n />\n );\n }\n if (resolved === 'pdf') {\n return (\n <iframe\n src={src}\n title={path}\n data-testid={testId}\n data-kind={resolved}\n className={cn(FRAME, 'h-[36rem] w-full', className)}\n />\n );\n }\n return (\n <Badge\n asChild\n size=\"md\"\n data-testid={testId}\n data-kind={resolved}\n className={cn('self-start bg-doom-panel text-doom-text hover:border-doom-blue/50', className)}\n >\n <a href={src} download={name}>\n <FileIcon className=\"h-3 w-3 shrink-0 text-doom-faint\" />\n download {name}\n </a>\n </Badge>\n );\n}\n"],"mappings":"sNA2BA,MAAM,EAAQ,4DAEd,SAAgB,EAAa,CAAE,MAAK,OAAM,OAAM,YAAW,cAAe,GAA6B,CACrG,IAAM,EAAW,GAAQ,EAAY,CAAI,EACnC,EAAO,EAAK,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAK,EAgCvC,OA9BI,IAAa,QAEb,EAAC,IAAD,CAAG,KAAM,EAAK,OAAO,SAAS,IAAI,aAAa,cAAa,EAAQ,YAAW,EAC7E,SAAA,EAAC,MAAD,CAAU,MAAK,IAAK,EAAM,UAAW,EAAG,EAAO,gBAAiB,CAAS,CAAI,CAAA,CAC5E,CAAA,EAGH,IAAa,QAEb,EAAC,QAAD,CACO,MACL,SAAA,GACA,QAAQ,WACR,cAAa,EACb,YAAW,EACX,UAAW,EAAG,EAAO,gBAAiB,CAAS,CAChD,CAAA,EAGD,IAAa,MAEb,EAAC,SAAD,CACO,MACL,MAAO,EACP,cAAa,EACb,YAAW,EACX,UAAW,EAAG,EAAO,mBAAoB,CAAS,CACnD,CAAA,EAIH,EAAC,EAAD,CACE,QAAA,GACA,KAAK,KACL,cAAa,EACb,YAAW,EACX,UAAW,EAAG,oEAAqE,CAAS,EAE5F,SAAA,EAAC,IAAD,CAAG,KAAM,EAAK,SAAU,EAAxB,SAAA,CACE,EAAC,EAAD,CAAU,UAAU,kCAAoC,CAAA,EAAC,YAC/C,CACT,GACE,CAAA,CAEX"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../lib/cn.cjs");let t=require("radix-ui"),n=require("react/jsx-runtime");function r(e){return(0,n.jsx)(t.Popover.Root,{"data-slot":`popover`,...e})}function i(e){return(0,n.jsx)(t.Popover.Trigger,{"data-slot":`popover-trigger`,...e})}function a(e){return(0,n.jsx)(t.Popover.Anchor,{"data-slot":`popover-anchor`,...e})}function o(e){return(0,n.jsx)(t.Popover.Close,{"data-slot":`popover-close`,...e})}function s({className:r,align:i=`start`,sideOffset:a=6,...o}){return(0,n.jsx)(t.Popover.Portal,{children:(0,n.jsx)(t.Popover.Content,{"data-slot":`popover-content`,align:i,sideOffset:a,className:e.cn(`z-50 flex flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-rise`,r),...o})})}function c({className:t,...r}){return(0,n.jsx)(`div`,{"data-slot":`popover-header`,className:e.cn(`flex h-[34px] shrink-0 items-center justify-between gap-3 border-b border-doom-border-soft bg-doom-deep px-3`,t),...r})}function l({className:t,...r}){return(0,n.jsx)(`div`,{"data-slot":`popover-footer`,className:e.cn(`flex min-h-[30px] shrink-0 items-center justify-between gap-3 border-t border-doom-border-soft bg-doom-deep px-3 text-[9px] text-doom-faint`,t),...r})}exports.Popover=r,exports.PopoverAnchor=a,exports.PopoverClose=o,exports.PopoverContent=s,exports.PopoverFooter=l,exports.PopoverHeader=c,exports.PopoverTrigger=i;
|
|
1
|
+
const e=require("../lib/cn.cjs");let t=require("radix-ui"),n=require("react/jsx-runtime");function r(e){return(0,n.jsx)(t.Popover.Root,{"data-slot":`popover`,...e})}function i(e){return(0,n.jsx)(t.Popover.Trigger,{"data-slot":`popover-trigger`,...e})}function a(e){return(0,n.jsx)(t.Popover.Anchor,{"data-slot":`popover-anchor`,...e})}function o(e){return(0,n.jsx)(t.Popover.Close,{"data-slot":`popover-close`,...e})}function s({className:r,align:i=`start`,sideOffset:a=6,...o}){return(0,n.jsx)(t.Popover.Portal,{children:(0,n.jsx)(t.Popover.Content,{"data-slot":`popover-content`,align:i,sideOffset:a,className:e.cn(`z-50 flex max-w-[calc(100vw-24px)] flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-rise`,r),...o})})}function c({className:t,...r}){return(0,n.jsx)(`div`,{"data-slot":`popover-header`,className:e.cn(`flex h-[34px] shrink-0 items-center justify-between gap-3 border-b border-doom-border-soft bg-doom-deep px-3`,t),...r})}function l({className:t,...r}){return(0,n.jsx)(`div`,{"data-slot":`popover-footer`,className:e.cn(`flex min-h-[30px] shrink-0 items-center justify-between gap-3 border-t border-doom-border-soft bg-doom-deep px-3 text-[9px] text-doom-faint`,t),...r})}exports.Popover=r,exports.PopoverAnchor=a,exports.PopoverClose=o,exports.PopoverContent=s,exports.PopoverFooter=l,exports.PopoverHeader=c,exports.PopoverTrigger=i;
|
|
2
2
|
//# sourceMappingURL=Popover.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.cjs","names":["PopoverPrimitive","cn"],"sources":["../../../src/components/Popover.tsx"],"sourcesContent":["import { Popover as PopoverPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\nimport { cn } from '../lib/cn.ts';\n\n/**\n * shadcn's Popover on Radix: anchored to its trigger, closes on outside\n * click and Escape, and the trigger toggles it rather than reopening it.\n */\nexport function Popover(props: ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nexport function PopoverTrigger(props: ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nexport function PopoverAnchor(props: ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\n\n/** Dismisses the popover from inside it: the row that acts and closes in one click. */\nexport function PopoverClose(props: ComponentProps<typeof PopoverPrimitive.Close>) {\n return <PopoverPrimitive.Close data-slot=\"popover-close\" {...props} />;\n}\n\nexport function PopoverContent({\n className,\n align = 'start',\n sideOffset = 6,\n ...props\n}: ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 flex flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-rise',\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\n/** The strip a popover's title sits in; tone colours the title. */\nexport function PopoverHeader({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\n 'flex h-[34px] shrink-0 items-center justify-between gap-3 border-b border-doom-border-soft bg-doom-deep px-3',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport function PopoverFooter({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"popover-footer\"\n className={cn(\n 'flex min-h-[30px] shrink-0 items-center justify-between gap-3 border-t border-doom-border-soft bg-doom-deep px-3 text-[9px] text-doom-faint',\n className,\n )}\n {...props}\n />\n );\n}\n"],"mappings":"0FAQA,SAAgB,EAAQ,EAAqD,CAC3E,OAAO,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,KAAlB,CAAuB,YAAU,UAAU,GAAI,CAAQ,CAAA,CAChE,CAEA,SAAgB,EAAe,EAAwD,CACrF,OAAO,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,QAAlB,CAA0B,YAAU,kBAAkB,GAAI,CAAQ,CAAA,CAC3E,CAEA,SAAgB,EAAc,EAAuD,CACnF,OAAO,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,OAAlB,CAAyB,YAAU,iBAAiB,GAAI,CAAQ,CAAA,CACzE,CAGA,SAAgB,EAAa,EAAsD,CACjF,OAAO,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,MAAlB,CAAwB,YAAU,gBAAgB,GAAI,CAAQ,CAAA,CACvE,CAEA,SAAgB,EAAe,CAC7B,YACA,QAAQ,QACR,aAAa,EACb,GAAG,GAC+C,CAClD,OACE,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,OAAlB,CAAA,UACE,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,QAAlB,CACE,YAAU,kBACH,QACK,aACZ,UAAWC,EAAAA,GACT,
|
|
1
|
+
{"version":3,"file":"Popover.cjs","names":["PopoverPrimitive","cn"],"sources":["../../../src/components/Popover.tsx"],"sourcesContent":["import { Popover as PopoverPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\nimport { cn } from '../lib/cn.ts';\n\n/**\n * shadcn's Popover on Radix: anchored to its trigger, closes on outside\n * click and Escape, and the trigger toggles it rather than reopening it.\n */\nexport function Popover(props: ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nexport function PopoverTrigger(props: ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nexport function PopoverAnchor(props: ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\n\n/** Dismisses the popover from inside it: the row that acts and closes in one click. */\nexport function PopoverClose(props: ComponentProps<typeof PopoverPrimitive.Close>) {\n return <PopoverPrimitive.Close data-slot=\"popover-close\" {...props} />;\n}\n\nexport function PopoverContent({\n className,\n align = 'start',\n sideOffset = 6,\n ...props\n}: ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 flex max-w-[calc(100vw-24px)] flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-rise',\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\n/** The strip a popover's title sits in; tone colours the title. */\nexport function PopoverHeader({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\n 'flex h-[34px] shrink-0 items-center justify-between gap-3 border-b border-doom-border-soft bg-doom-deep px-3',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport function PopoverFooter({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"popover-footer\"\n className={cn(\n 'flex min-h-[30px] shrink-0 items-center justify-between gap-3 border-t border-doom-border-soft bg-doom-deep px-3 text-[9px] text-doom-faint',\n className,\n )}\n {...props}\n />\n );\n}\n"],"mappings":"0FAQA,SAAgB,EAAQ,EAAqD,CAC3E,OAAO,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,KAAlB,CAAuB,YAAU,UAAU,GAAI,CAAQ,CAAA,CAChE,CAEA,SAAgB,EAAe,EAAwD,CACrF,OAAO,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,QAAlB,CAA0B,YAAU,kBAAkB,GAAI,CAAQ,CAAA,CAC3E,CAEA,SAAgB,EAAc,EAAuD,CACnF,OAAO,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,OAAlB,CAAyB,YAAU,iBAAiB,GAAI,CAAQ,CAAA,CACzE,CAGA,SAAgB,EAAa,EAAsD,CACjF,OAAO,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,MAAlB,CAAwB,YAAU,gBAAgB,GAAI,CAAQ,CAAA,CACvE,CAEA,SAAgB,EAAe,CAC7B,YACA,QAAQ,QACR,aAAa,EACb,GAAG,GAC+C,CAClD,OACE,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,OAAlB,CAAA,UACE,EAAA,EAAA,IAAA,CAACA,EAAAA,QAAiB,QAAlB,CACE,YAAU,kBACH,QACK,aACZ,UAAWC,EAAAA,GACT,uLACA,CACF,EACA,GAAI,CACL,CAAA,CACsB,CAAA,CAE7B,CAGA,SAAgB,EAAc,CAAE,YAAW,GAAG,GAAgC,CAC5E,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,YAAU,iBACV,UAAWA,EAAAA,GACT,+GACA,CACF,EACA,GAAI,CACL,CAAA,CAEL,CAEA,SAAgB,EAAc,CAAE,YAAW,GAAG,GAAgC,CAC5E,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,YAAU,iBACV,UAAWA,EAAAA,GACT,8IACA,CACF,EACA,GAAI,CACL,CAAA,CAEL"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{cn as e}from"../lib/cn.mjs";import{Popover as t}from"radix-ui";import{jsx as n}from"react/jsx-runtime";function r(e){return n(t.Root,{"data-slot":`popover`,...e})}function i(e){return n(t.Trigger,{"data-slot":`popover-trigger`,...e})}function a(e){return n(t.Anchor,{"data-slot":`popover-anchor`,...e})}function o(e){return n(t.Close,{"data-slot":`popover-close`,...e})}function s({className:r,align:i=`start`,sideOffset:a=6,...o}){return n(t.Portal,{children:n(t.Content,{"data-slot":`popover-content`,align:i,sideOffset:a,className:e(`z-50 flex flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-rise`,r),...o})})}function c({className:t,...r}){return n(`div`,{"data-slot":`popover-header`,className:e(`flex h-[34px] shrink-0 items-center justify-between gap-3 border-b border-doom-border-soft bg-doom-deep px-3`,t),...r})}function l({className:t,...r}){return n(`div`,{"data-slot":`popover-footer`,className:e(`flex min-h-[30px] shrink-0 items-center justify-between gap-3 border-t border-doom-border-soft bg-doom-deep px-3 text-[9px] text-doom-faint`,t),...r})}export{r as Popover,a as PopoverAnchor,o as PopoverClose,s as PopoverContent,l as PopoverFooter,c as PopoverHeader,i as PopoverTrigger};
|
|
1
|
+
import{cn as e}from"../lib/cn.mjs";import{Popover as t}from"radix-ui";import{jsx as n}from"react/jsx-runtime";function r(e){return n(t.Root,{"data-slot":`popover`,...e})}function i(e){return n(t.Trigger,{"data-slot":`popover-trigger`,...e})}function a(e){return n(t.Anchor,{"data-slot":`popover-anchor`,...e})}function o(e){return n(t.Close,{"data-slot":`popover-close`,...e})}function s({className:r,align:i=`start`,sideOffset:a=6,...o}){return n(t.Portal,{children:n(t.Content,{"data-slot":`popover-content`,align:i,sideOffset:a,className:e(`z-50 flex max-w-[calc(100vw-24px)] flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-rise`,r),...o})})}function c({className:t,...r}){return n(`div`,{"data-slot":`popover-header`,className:e(`flex h-[34px] shrink-0 items-center justify-between gap-3 border-b border-doom-border-soft bg-doom-deep px-3`,t),...r})}function l({className:t,...r}){return n(`div`,{"data-slot":`popover-footer`,className:e(`flex min-h-[30px] shrink-0 items-center justify-between gap-3 border-t border-doom-border-soft bg-doom-deep px-3 text-[9px] text-doom-faint`,t),...r})}export{r as Popover,a as PopoverAnchor,o as PopoverClose,s as PopoverContent,l as PopoverFooter,c as PopoverHeader,i as PopoverTrigger};
|
|
2
2
|
//# sourceMappingURL=Popover.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.mjs","names":["Popover","PopoverPrimitive"],"sources":["../../../src/components/Popover.tsx"],"sourcesContent":["import { Popover as PopoverPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\nimport { cn } from '../lib/cn.ts';\n\n/**\n * shadcn's Popover on Radix: anchored to its trigger, closes on outside\n * click and Escape, and the trigger toggles it rather than reopening it.\n */\nexport function Popover(props: ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nexport function PopoverTrigger(props: ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nexport function PopoverAnchor(props: ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\n\n/** Dismisses the popover from inside it: the row that acts and closes in one click. */\nexport function PopoverClose(props: ComponentProps<typeof PopoverPrimitive.Close>) {\n return <PopoverPrimitive.Close data-slot=\"popover-close\" {...props} />;\n}\n\nexport function PopoverContent({\n className,\n align = 'start',\n sideOffset = 6,\n ...props\n}: ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 flex flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-rise',\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\n/** The strip a popover's title sits in; tone colours the title. */\nexport function PopoverHeader({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\n 'flex h-[34px] shrink-0 items-center justify-between gap-3 border-b border-doom-border-soft bg-doom-deep px-3',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport function PopoverFooter({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"popover-footer\"\n className={cn(\n 'flex min-h-[30px] shrink-0 items-center justify-between gap-3 border-t border-doom-border-soft bg-doom-deep px-3 text-[9px] text-doom-faint',\n className,\n )}\n {...props}\n />\n );\n}\n"],"mappings":"8GAQA,SAAgBA,EAAQ,EAAqD,CAC3E,OAAO,EAACC,EAAiB,KAAlB,CAAuB,YAAU,UAAU,GAAI,CAAQ,CAAA,CAChE,CAEA,SAAgB,EAAe,EAAwD,CACrF,OAAO,EAACA,EAAiB,QAAlB,CAA0B,YAAU,kBAAkB,GAAI,CAAQ,CAAA,CAC3E,CAEA,SAAgB,EAAc,EAAuD,CACnF,OAAO,EAACA,EAAiB,OAAlB,CAAyB,YAAU,iBAAiB,GAAI,CAAQ,CAAA,CACzE,CAGA,SAAgB,EAAa,EAAsD,CACjF,OAAO,EAACA,EAAiB,MAAlB,CAAwB,YAAU,gBAAgB,GAAI,CAAQ,CAAA,CACvE,CAEA,SAAgB,EAAe,CAC7B,YACA,QAAQ,QACR,aAAa,EACb,GAAG,GAC+C,CAClD,OACE,EAACA,EAAiB,OAAlB,CAAA,SACE,EAACA,EAAiB,QAAlB,CACE,YAAU,kBACH,QACK,aACZ,UAAW,EACT,
|
|
1
|
+
{"version":3,"file":"Popover.mjs","names":["Popover","PopoverPrimitive"],"sources":["../../../src/components/Popover.tsx"],"sourcesContent":["import { Popover as PopoverPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\nimport { cn } from '../lib/cn.ts';\n\n/**\n * shadcn's Popover on Radix: anchored to its trigger, closes on outside\n * click and Escape, and the trigger toggles it rather than reopening it.\n */\nexport function Popover(props: ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nexport function PopoverTrigger(props: ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nexport function PopoverAnchor(props: ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\n\n/** Dismisses the popover from inside it: the row that acts and closes in one click. */\nexport function PopoverClose(props: ComponentProps<typeof PopoverPrimitive.Close>) {\n return <PopoverPrimitive.Close data-slot=\"popover-close\" {...props} />;\n}\n\nexport function PopoverContent({\n className,\n align = 'start',\n sideOffset = 6,\n ...props\n}: ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 flex max-w-[calc(100vw-24px)] flex-col overflow-hidden rounded-lg border border-doom-border bg-doom-panel font-mono shadow-2xl outline-none data-[state=open]:animate-doom-rise',\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\n/** The strip a popover's title sits in; tone colours the title. */\nexport function PopoverHeader({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\n 'flex h-[34px] shrink-0 items-center justify-between gap-3 border-b border-doom-border-soft bg-doom-deep px-3',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport function PopoverFooter({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"popover-footer\"\n className={cn(\n 'flex min-h-[30px] shrink-0 items-center justify-between gap-3 border-t border-doom-border-soft bg-doom-deep px-3 text-[9px] text-doom-faint',\n className,\n )}\n {...props}\n />\n );\n}\n"],"mappings":"8GAQA,SAAgBA,EAAQ,EAAqD,CAC3E,OAAO,EAACC,EAAiB,KAAlB,CAAuB,YAAU,UAAU,GAAI,CAAQ,CAAA,CAChE,CAEA,SAAgB,EAAe,EAAwD,CACrF,OAAO,EAACA,EAAiB,QAAlB,CAA0B,YAAU,kBAAkB,GAAI,CAAQ,CAAA,CAC3E,CAEA,SAAgB,EAAc,EAAuD,CACnF,OAAO,EAACA,EAAiB,OAAlB,CAAyB,YAAU,iBAAiB,GAAI,CAAQ,CAAA,CACzE,CAGA,SAAgB,EAAa,EAAsD,CACjF,OAAO,EAACA,EAAiB,MAAlB,CAAwB,YAAU,gBAAgB,GAAI,CAAQ,CAAA,CACvE,CAEA,SAAgB,EAAe,CAC7B,YACA,QAAQ,QACR,aAAa,EACb,GAAG,GAC+C,CAClD,OACE,EAACA,EAAiB,OAAlB,CAAA,SACE,EAACA,EAAiB,QAAlB,CACE,YAAU,kBACH,QACK,aACZ,UAAW,EACT,uLACA,CACF,EACA,GAAI,CACL,CAAA,CACsB,CAAA,CAE7B,CAGA,SAAgB,EAAc,CAAE,YAAW,GAAG,GAAgC,CAC5E,OACE,EAAC,MAAD,CACE,YAAU,iBACV,UAAW,EACT,+GACA,CACF,EACA,GAAI,CACL,CAAA,CAEL,CAEA,SAAgB,EAAc,CAAE,YAAW,GAAG,GAAgC,CAC5E,OACE,EAAC,MAAD,CACE,YAAU,iBACV,UAAW,EACT,8IACA,CACF,EACA,GAAI,CACL,CAAA,CAEL"}
|
package/dist/src/icons/icons.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let e=require("lucide-react");Object.defineProperty(exports,"ActivityIcon",{enumerable:!0,get:function(){return e.Activity}}),Object.defineProperty(exports,"AlertIcon",{enumerable:!0,get:function(){return e.CircleAlert}}),Object.defineProperty(exports,"BranchIcon",{enumerable:!0,get:function(){return e.GitBranch}}),Object.defineProperty(exports,"CheckIcon",{enumerable:!0,get:function(){return e.Check}}),Object.defineProperty(exports,"ChevronDownIcon",{enumerable:!0,get:function(){return e.ChevronDown}}),Object.defineProperty(exports,"ChevronRightIcon",{enumerable:!0,get:function(){return e.ChevronRight}}),Object.defineProperty(exports,"ChevronUpIcon",{enumerable:!0,get:function(){return e.ChevronUp}}),Object.defineProperty(exports,"CloseIcon",{enumerable:!0,get:function(){return e.X}}),Object.defineProperty(exports,"EnterIcon",{enumerable:!0,get:function(){return e.CornerDownLeft}}),Object.defineProperty(exports,"ExternalLinkIcon",{enumerable:!0,get:function(){return e.ExternalLink}}),Object.defineProperty(exports,"FileIcon",{enumerable:!0,get:function(){return e.FileText}}),Object.defineProperty(exports,"GearIcon",{enumerable:!0,get:function(){return e.Settings}}),Object.defineProperty(exports,"KebabIcon",{enumerable:!0,get:function(){return e.MoreVertical}}),Object.defineProperty(exports,"LoaderIcon",{enumerable:!0,get:function(){return e.Loader2}}),Object.defineProperty(exports,"PaletteIcon",{enumerable:!0,get:function(){return e.Palette}}),Object.defineProperty(exports,"PlusIcon",{enumerable:!0,get:function(){return e.Plus}}),Object.defineProperty(exports,"RefreshIcon",{enumerable:!0,get:function(){return e.RefreshCw}}),Object.defineProperty(exports,"SearchIcon",{enumerable:!0,get:function(){return e.Search}}),Object.defineProperty(exports,"ShieldIcon",{enumerable:!0,get:function(){return e.ShieldCheck}}),Object.defineProperty(exports,"StopIcon",{enumerable:!0,get:function(){return e.Square}});
|
|
1
|
+
let e=require("lucide-react");Object.defineProperty(exports,"ActivityIcon",{enumerable:!0,get:function(){return e.Activity}}),Object.defineProperty(exports,"AlertIcon",{enumerable:!0,get:function(){return e.CircleAlert}}),Object.defineProperty(exports,"AudioLinesIcon",{enumerable:!0,get:function(){return e.AudioLines}}),Object.defineProperty(exports,"BranchIcon",{enumerable:!0,get:function(){return e.GitBranch}}),Object.defineProperty(exports,"CheckIcon",{enumerable:!0,get:function(){return e.Check}}),Object.defineProperty(exports,"ChevronDownIcon",{enumerable:!0,get:function(){return e.ChevronDown}}),Object.defineProperty(exports,"ChevronRightIcon",{enumerable:!0,get:function(){return e.ChevronRight}}),Object.defineProperty(exports,"ChevronUpIcon",{enumerable:!0,get:function(){return e.ChevronUp}}),Object.defineProperty(exports,"CloseIcon",{enumerable:!0,get:function(){return e.X}}),Object.defineProperty(exports,"EditIcon",{enumerable:!0,get:function(){return e.Pencil}}),Object.defineProperty(exports,"EnterIcon",{enumerable:!0,get:function(){return e.CornerDownLeft}}),Object.defineProperty(exports,"ExternalLinkIcon",{enumerable:!0,get:function(){return e.ExternalLink}}),Object.defineProperty(exports,"FileIcon",{enumerable:!0,get:function(){return e.FileText}}),Object.defineProperty(exports,"GearIcon",{enumerable:!0,get:function(){return e.Settings}}),Object.defineProperty(exports,"KebabIcon",{enumerable:!0,get:function(){return e.MoreVertical}}),Object.defineProperty(exports,"LoaderIcon",{enumerable:!0,get:function(){return e.Loader2}}),Object.defineProperty(exports,"MessageIcon",{enumerable:!0,get:function(){return e.MessageCircle}}),Object.defineProperty(exports,"MicIcon",{enumerable:!0,get:function(){return e.Mic}}),Object.defineProperty(exports,"PaletteIcon",{enumerable:!0,get:function(){return e.Palette}}),Object.defineProperty(exports,"PlusIcon",{enumerable:!0,get:function(){return e.Plus}}),Object.defineProperty(exports,"RefreshIcon",{enumerable:!0,get:function(){return e.RefreshCw}}),Object.defineProperty(exports,"SearchIcon",{enumerable:!0,get:function(){return e.Search}}),Object.defineProperty(exports,"SendIcon",{enumerable:!0,get:function(){return e.Send}}),Object.defineProperty(exports,"ShieldIcon",{enumerable:!0,get:function(){return e.ShieldCheck}}),Object.defineProperty(exports,"StopIcon",{enumerable:!0,get:function(){return e.Square}}),Object.defineProperty(exports,"TrashIcon",{enumerable:!0,get:function(){return e.Trash2}}),Object.defineProperty(exports,"VolumeIcon",{enumerable:!0,get:function(){return e.Volume2}});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Activity as ActivityIcon, Check as CheckIcon, ChevronDown as ChevronDownIcon, ChevronRight as ChevronRightIcon, ChevronUp as ChevronUpIcon, CircleAlert as AlertIcon, CornerDownLeft as EnterIcon, ExternalLink as ExternalLinkIcon, FileText as FileIcon, GitBranch as BranchIcon, Loader2 as LoaderIcon, MoreVertical as KebabIcon, Palette as PaletteIcon, Plus as PlusIcon, RefreshCw as RefreshIcon, Search as SearchIcon, Settings as GearIcon, ShieldCheck as ShieldIcon, Square as StopIcon, X as CloseIcon } from "lucide-react";
|
|
2
|
-
export { ActivityIcon, AlertIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, EnterIcon, ExternalLinkIcon, FileIcon, GearIcon, KebabIcon, LoaderIcon, PaletteIcon, PlusIcon, RefreshIcon, SearchIcon, ShieldIcon, StopIcon };
|
|
1
|
+
import { Activity as ActivityIcon, AudioLines as AudioLinesIcon, Check as CheckIcon, ChevronDown as ChevronDownIcon, ChevronRight as ChevronRightIcon, ChevronUp as ChevronUpIcon, CircleAlert as AlertIcon, CornerDownLeft as EnterIcon, ExternalLink as ExternalLinkIcon, FileText as FileIcon, GitBranch as BranchIcon, Loader2 as LoaderIcon, MessageCircle as MessageIcon, Mic as MicIcon, MoreVertical as KebabIcon, Palette as PaletteIcon, Pencil as EditIcon, Plus as PlusIcon, RefreshCw as RefreshIcon, Search as SearchIcon, Send as SendIcon, Settings as GearIcon, ShieldCheck as ShieldIcon, Square as StopIcon, Trash2 as TrashIcon, Volume2 as VolumeIcon, X as CloseIcon } from "lucide-react";
|
|
2
|
+
export { ActivityIcon, AlertIcon, AudioLinesIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, EditIcon, EnterIcon, ExternalLinkIcon, FileIcon, GearIcon, KebabIcon, LoaderIcon, MessageIcon, MicIcon, PaletteIcon, PlusIcon, RefreshIcon, SearchIcon, SendIcon, ShieldIcon, StopIcon, TrashIcon, VolumeIcon };
|
package/dist/src/icons/icons.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Activity as e,
|
|
1
|
+
import{Activity as e,AudioLines as t,Check as n,ChevronDown as r,ChevronRight as i,ChevronUp as a,CircleAlert as o,CornerDownLeft as s,ExternalLink as c,FileText as l,GitBranch as u,Loader2 as d,MessageCircle as f,Mic as p,MoreVertical as m,Palette as h,Pencil as g,Plus as _,RefreshCw as v,Search as y,Send as b,Settings as x,ShieldCheck as S,Square as C,Trash2 as w,Volume2 as T,X as E}from"lucide-react";export{e as ActivityIcon,o as AlertIcon,t as AudioLinesIcon,u as BranchIcon,n as CheckIcon,r as ChevronDownIcon,i as ChevronRightIcon,a as ChevronUpIcon,E as CloseIcon,g as EditIcon,s as EnterIcon,c as ExternalLinkIcon,l as FileIcon,x as GearIcon,m as KebabIcon,d as LoaderIcon,f as MessageIcon,p as MicIcon,h as PaletteIcon,_ as PlusIcon,v as RefreshIcon,y as SearchIcon,b as SendIcon,S as ShieldIcon,C as StopIcon,w as TrashIcon,T as VolumeIcon};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={cjs:`javascript`,js:`javascript`,mjs:`javascript`,jsx:`jsx`,cts:`typescript`,mts:`typescript`,ts:`typescript`,tsx:`tsx`,json:`json`,jsonc:`json`,markdown:`markdown`,md:`markdown`,htm:`html`,html:`html`,xhtml:`html`,css:`css`,py:`python`,pyi:`python`,yaml:`yaml`,yml:`yaml`,bash:`shell`,sh:`shell`,zsh:`shell`,toml:`toml`},t={".bashrc":`shell`,".zshrc":`shell`,containerfile:`dockerfile`,dockerfile:`dockerfile`};function n(e){return(e.split(`/`).at(-1)??``).toLowerCase()}function r(r){let i=n(r),a=t[i];if(a!==void 0)return a;let o=i.lastIndexOf(`.`);if(!(o<1))return e[i.slice(o+1)]}async function i(e){let[{StreamLanguage:t},n]=await Promise.all([import(`@codemirror/language`),e()]);return t.define(n)}async function a(e){switch(e){case`javascript`:return(await import(`@codemirror/lang-javascript`)).javascript();case`jsx`:return(await import(`@codemirror/lang-javascript`)).javascript({jsx:!0});case`typescript`:return(await import(`@codemirror/lang-javascript`)).javascript({typescript:!0});case`tsx`:return(await import(`@codemirror/lang-javascript`)).javascript({jsx:!0,typescript:!0});case`json`:return(await import(`@codemirror/lang-json`)).json();case`markdown`:return(await import(`@codemirror/lang-markdown`)).markdown();case`html`:return(await import(`@codemirror/lang-html`)).html();case`css`:return(await import(`@codemirror/lang-css`)).css();case`python`:return(await import(`@codemirror/lang-python`)).python();case`yaml`:return(await import(`@codemirror/lang-yaml`)).yaml();case`shell`:return i(async()=>(await import(`@codemirror/legacy-modes/mode/shell`)).shell);case`toml`:return i(async()=>(await import(`@codemirror/legacy-modes/mode/toml`)).toml);case`dockerfile`:return i(async()=>(await import(`@codemirror/legacy-modes/mode/dockerfile`)).dockerFile)}}exports.grammarKeyOf=r,exports.loadGrammar=a;
|
|
2
|
+
//# sourceMappingURL=editorLanguage.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorLanguage.cjs","names":[],"sources":["../../../src/lib/editorLanguage.ts"],"sourcesContent":["import type { StreamParser } from '@codemirror/language';\nimport type { Extension } from '@codemirror/state';\n\n/**\n * Which grammar a file gets, and how it arrives.\n *\n * The two halves are apart on purpose. Naming the grammar is a pure lookup a\n * caller can run before deciding anything, and loading it is a dynamic import\n * so a session that only ever opens Markdown never downloads the JavaScript\n * parser. Nothing here imports CodeMirror at runtime: every specifier below is\n * either a type, which erases, or inside an `import()` the bundler splits into\n * its own chunk.\n */\n\nexport type GrammarKey =\n | 'javascript'\n | 'jsx'\n | 'typescript'\n | 'tsx'\n | 'json'\n | 'markdown'\n | 'html'\n | 'css'\n | 'python'\n | 'yaml'\n | 'shell'\n | 'toml'\n | 'dockerfile';\n\n/** Keyed by lower-case extension without the dot. */\nconst GRAMMAR_BY_EXTENSION: Readonly<Record<string, GrammarKey>> = {\n cjs: 'javascript',\n js: 'javascript',\n mjs: 'javascript',\n jsx: 'jsx',\n cts: 'typescript',\n mts: 'typescript',\n ts: 'typescript',\n tsx: 'tsx',\n json: 'json',\n jsonc: 'json',\n markdown: 'markdown',\n md: 'markdown',\n htm: 'html',\n html: 'html',\n xhtml: 'html',\n css: 'css',\n py: 'python',\n pyi: 'python',\n yaml: 'yaml',\n yml: 'yaml',\n bash: 'shell',\n sh: 'shell',\n zsh: 'shell',\n toml: 'toml',\n};\n\n/** Files a project names rather than suffixes, matched on the whole lower-cased basename. */\nconst GRAMMAR_BY_FILENAME: Readonly<Record<string, GrammarKey>> = {\n '.bashrc': 'shell',\n '.zshrc': 'shell',\n containerfile: 'dockerfile',\n dockerfile: 'dockerfile',\n};\n\n/** The last segment of a path, lower-cased. */\nfunction basenameOf(filePath: string): string {\n return (filePath.split('/').at(-1) ?? '').toLowerCase();\n}\n\n/**\n * The grammar for a path, or undefined for a file the editor shows as plain\n * text. A name is tried whole before it is tried as a suffix, so\n * `Dockerfile.dev` is a Dockerfile and not a file with a `dev` extension.\n */\nexport function grammarKeyOf(filePath: string): GrammarKey | undefined {\n const name = basenameOf(filePath);\n const named = GRAMMAR_BY_FILENAME[name];\n if (named !== undefined) return named;\n const dot = name.lastIndexOf('.');\n if (dot < 1) return undefined;\n return GRAMMAR_BY_EXTENSION[name.slice(dot + 1)];\n}\n\n/** A legacy stream mode wrapped as a language; the modes predate Lezer and ship as tokenizers. */\nasync function streamMode(load: () => Promise<StreamParser<unknown>>): Promise<Extension> {\n const [{ StreamLanguage }, parser] = await Promise.all([import('@codemirror/language'), load()]);\n return StreamLanguage.define(parser);\n}\n\n/** Downloads one grammar. Each arm is its own chunk, so the cost is the languages actually opened. */\nexport async function loadGrammar(key: GrammarKey): Promise<Extension> {\n switch (key) {\n case 'javascript':\n return (await import('@codemirror/lang-javascript')).javascript();\n case 'jsx':\n return (await import('@codemirror/lang-javascript')).javascript({ jsx: true });\n case 'typescript':\n return (await import('@codemirror/lang-javascript')).javascript({ typescript: true });\n case 'tsx':\n return (await import('@codemirror/lang-javascript')).javascript({ jsx: true, typescript: true });\n case 'json':\n return (await import('@codemirror/lang-json')).json();\n case 'markdown':\n return (await import('@codemirror/lang-markdown')).markdown();\n case 'html':\n return (await import('@codemirror/lang-html')).html();\n case 'css':\n return (await import('@codemirror/lang-css')).css();\n case 'python':\n return (await import('@codemirror/lang-python')).python();\n case 'yaml':\n return (await import('@codemirror/lang-yaml')).yaml();\n case 'shell':\n return streamMode(async () => (await import('@codemirror/legacy-modes/mode/shell')).shell);\n case 'toml':\n return streamMode(async () => (await import('@codemirror/legacy-modes/mode/toml')).toml);\n case 'dockerfile':\n return streamMode(async () => (await import('@codemirror/legacy-modes/mode/dockerfile')).dockerFile);\n }\n}\n"],"mappings":"AA8BA,MAAM,EAA6D,CACjE,IAAK,aACL,GAAI,aACJ,IAAK,aACL,IAAK,MACL,IAAK,aACL,IAAK,aACL,GAAI,aACJ,IAAK,MACL,KAAM,OACN,MAAO,OACP,SAAU,WACV,GAAI,WACJ,IAAK,OACL,KAAM,OACN,MAAO,OACP,IAAK,MACL,GAAI,SACJ,IAAK,SACL,KAAM,OACN,IAAK,OACL,KAAM,QACN,GAAI,QACJ,IAAK,QACL,KAAM,MACR,EAGM,EAA4D,CAChE,UAAW,QACX,SAAU,QACV,cAAe,aACf,WAAY,YACd,EAGA,SAAS,EAAW,EAA0B,CAC5C,OAAQ,EAAS,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAK,GAAA,CAAI,YAAY,CACxD,CAOA,SAAgB,EAAa,EAA0C,CACrE,IAAM,EAAO,EAAW,CAAQ,EAC1B,EAAQ,EAAoB,GAClC,GAAI,IAAU,IAAA,GAAW,OAAO,EAChC,IAAM,EAAM,EAAK,YAAY,GAAG,EAC5B,OAAM,GACV,OAAO,EAAqB,EAAK,MAAM,EAAM,CAAC,EAChD,CAGA,eAAe,EAAW,EAAgE,CACxF,GAAM,CAAC,CAAE,kBAAkB,GAAU,MAAM,QAAQ,IAAI,CAAC,OAAO,wBAAyB,EAAK,CAAC,CAAC,EAC/F,OAAO,EAAe,OAAO,CAAM,CACrC,CAGA,eAAsB,EAAY,EAAqC,CACrE,OAAQ,EAAR,CACE,IAAK,aACH,OAAQ,MAAM,OAAO,+BAAA,CAAgC,WAAW,EAClE,IAAK,MACH,OAAQ,MAAM,OAAO,+BAAA,CAAgC,WAAW,CAAE,IAAK,EAAK,CAAC,EAC/E,IAAK,aACH,OAAQ,MAAM,OAAO,+BAAA,CAAgC,WAAW,CAAE,WAAY,EAAK,CAAC,EACtF,IAAK,MACH,OAAQ,MAAM,OAAO,+BAAA,CAAgC,WAAW,CAAE,IAAK,GAAM,WAAY,EAAK,CAAC,EACjG,IAAK,OACH,OAAQ,MAAM,OAAO,yBAAA,CAA0B,KAAK,EACtD,IAAK,WACH,OAAQ,MAAM,OAAO,6BAAA,CAA8B,SAAS,EAC9D,IAAK,OACH,OAAQ,MAAM,OAAO,yBAAA,CAA0B,KAAK,EACtD,IAAK,MACH,OAAQ,MAAM,OAAO,wBAAA,CAAyB,IAAI,EACpD,IAAK,SACH,OAAQ,MAAM,OAAO,2BAAA,CAA4B,OAAO,EAC1D,IAAK,OACH,OAAQ,MAAM,OAAO,yBAAA,CAA0B,KAAK,EACtD,IAAK,QACH,OAAO,EAAW,UAAa,MAAM,OAAO,uCAAA,CAAwC,KAAK,EAC3F,IAAK,OACH,OAAO,EAAW,UAAa,MAAM,OAAO,sCAAA,CAAuC,IAAI,EACzF,IAAK,aACH,OAAO,EAAW,UAAa,MAAM,OAAO,4CAAA,CAA6C,UAAU,CACvG,CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "@codemirror/state";
|
|
2
|
+
//#region src/lib/editorLanguage.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Which grammar a file gets, and how it arrives.
|
|
5
|
+
*
|
|
6
|
+
* The two halves are apart on purpose. Naming the grammar is a pure lookup a
|
|
7
|
+
* caller can run before deciding anything, and loading it is a dynamic import
|
|
8
|
+
* so a session that only ever opens Markdown never downloads the JavaScript
|
|
9
|
+
* parser. Nothing here imports CodeMirror at runtime: every specifier below is
|
|
10
|
+
* either a type, which erases, or inside an `import()` the bundler splits into
|
|
11
|
+
* its own chunk.
|
|
12
|
+
*/
|
|
13
|
+
type GrammarKey = 'javascript' | 'jsx' | 'typescript' | 'tsx' | 'json' | 'markdown' | 'html' | 'css' | 'python' | 'yaml' | 'shell' | 'toml' | 'dockerfile';
|
|
14
|
+
/**
|
|
15
|
+
* The grammar for a path, or undefined for a file the editor shows as plain
|
|
16
|
+
* text. A name is tried whole before it is tried as a suffix, so
|
|
17
|
+
* `Dockerfile.dev` is a Dockerfile and not a file with a `dev` extension.
|
|
18
|
+
*/
|
|
19
|
+
declare function grammarKeyOf(filePath: string): GrammarKey | undefined;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { GrammarKey, grammarKeyOf };
|
|
22
|
+
//# sourceMappingURL=editorLanguage.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorLanguage.d.mts","names":[],"sources":["../../../src/lib/editorLanguage.ts"],"mappings":";;;;;;;;;;;;KAcY;;;;;;iBA6DI,aAAa,mBAAmB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={cjs:`javascript`,js:`javascript`,mjs:`javascript`,jsx:`jsx`,cts:`typescript`,mts:`typescript`,ts:`typescript`,tsx:`tsx`,json:`json`,jsonc:`json`,markdown:`markdown`,md:`markdown`,htm:`html`,html:`html`,xhtml:`html`,css:`css`,py:`python`,pyi:`python`,yaml:`yaml`,yml:`yaml`,bash:`shell`,sh:`shell`,zsh:`shell`,toml:`toml`},t={".bashrc":`shell`,".zshrc":`shell`,containerfile:`dockerfile`,dockerfile:`dockerfile`};function n(e){return(e.split(`/`).at(-1)??``).toLowerCase()}function r(r){let i=n(r),a=t[i];if(a!==void 0)return a;let o=i.lastIndexOf(`.`);if(!(o<1))return e[i.slice(o+1)]}async function i(e){let[{StreamLanguage:t},n]=await Promise.all([import(`@codemirror/language`),e()]);return t.define(n)}async function a(e){switch(e){case`javascript`:return(await import(`@codemirror/lang-javascript`)).javascript();case`jsx`:return(await import(`@codemirror/lang-javascript`)).javascript({jsx:!0});case`typescript`:return(await import(`@codemirror/lang-javascript`)).javascript({typescript:!0});case`tsx`:return(await import(`@codemirror/lang-javascript`)).javascript({jsx:!0,typescript:!0});case`json`:return(await import(`@codemirror/lang-json`)).json();case`markdown`:return(await import(`@codemirror/lang-markdown`)).markdown();case`html`:return(await import(`@codemirror/lang-html`)).html();case`css`:return(await import(`@codemirror/lang-css`)).css();case`python`:return(await import(`@codemirror/lang-python`)).python();case`yaml`:return(await import(`@codemirror/lang-yaml`)).yaml();case`shell`:return i(async()=>(await import(`@codemirror/legacy-modes/mode/shell`)).shell);case`toml`:return i(async()=>(await import(`@codemirror/legacy-modes/mode/toml`)).toml);case`dockerfile`:return i(async()=>(await import(`@codemirror/legacy-modes/mode/dockerfile`)).dockerFile)}}export{r as grammarKeyOf,a as loadGrammar};
|
|
2
|
+
//# sourceMappingURL=editorLanguage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorLanguage.mjs","names":[],"sources":["../../../src/lib/editorLanguage.ts"],"sourcesContent":["import type { StreamParser } from '@codemirror/language';\nimport type { Extension } from '@codemirror/state';\n\n/**\n * Which grammar a file gets, and how it arrives.\n *\n * The two halves are apart on purpose. Naming the grammar is a pure lookup a\n * caller can run before deciding anything, and loading it is a dynamic import\n * so a session that only ever opens Markdown never downloads the JavaScript\n * parser. Nothing here imports CodeMirror at runtime: every specifier below is\n * either a type, which erases, or inside an `import()` the bundler splits into\n * its own chunk.\n */\n\nexport type GrammarKey =\n | 'javascript'\n | 'jsx'\n | 'typescript'\n | 'tsx'\n | 'json'\n | 'markdown'\n | 'html'\n | 'css'\n | 'python'\n | 'yaml'\n | 'shell'\n | 'toml'\n | 'dockerfile';\n\n/** Keyed by lower-case extension without the dot. */\nconst GRAMMAR_BY_EXTENSION: Readonly<Record<string, GrammarKey>> = {\n cjs: 'javascript',\n js: 'javascript',\n mjs: 'javascript',\n jsx: 'jsx',\n cts: 'typescript',\n mts: 'typescript',\n ts: 'typescript',\n tsx: 'tsx',\n json: 'json',\n jsonc: 'json',\n markdown: 'markdown',\n md: 'markdown',\n htm: 'html',\n html: 'html',\n xhtml: 'html',\n css: 'css',\n py: 'python',\n pyi: 'python',\n yaml: 'yaml',\n yml: 'yaml',\n bash: 'shell',\n sh: 'shell',\n zsh: 'shell',\n toml: 'toml',\n};\n\n/** Files a project names rather than suffixes, matched on the whole lower-cased basename. */\nconst GRAMMAR_BY_FILENAME: Readonly<Record<string, GrammarKey>> = {\n '.bashrc': 'shell',\n '.zshrc': 'shell',\n containerfile: 'dockerfile',\n dockerfile: 'dockerfile',\n};\n\n/** The last segment of a path, lower-cased. */\nfunction basenameOf(filePath: string): string {\n return (filePath.split('/').at(-1) ?? '').toLowerCase();\n}\n\n/**\n * The grammar for a path, or undefined for a file the editor shows as plain\n * text. A name is tried whole before it is tried as a suffix, so\n * `Dockerfile.dev` is a Dockerfile and not a file with a `dev` extension.\n */\nexport function grammarKeyOf(filePath: string): GrammarKey | undefined {\n const name = basenameOf(filePath);\n const named = GRAMMAR_BY_FILENAME[name];\n if (named !== undefined) return named;\n const dot = name.lastIndexOf('.');\n if (dot < 1) return undefined;\n return GRAMMAR_BY_EXTENSION[name.slice(dot + 1)];\n}\n\n/** A legacy stream mode wrapped as a language; the modes predate Lezer and ship as tokenizers. */\nasync function streamMode(load: () => Promise<StreamParser<unknown>>): Promise<Extension> {\n const [{ StreamLanguage }, parser] = await Promise.all([import('@codemirror/language'), load()]);\n return StreamLanguage.define(parser);\n}\n\n/** Downloads one grammar. Each arm is its own chunk, so the cost is the languages actually opened. */\nexport async function loadGrammar(key: GrammarKey): Promise<Extension> {\n switch (key) {\n case 'javascript':\n return (await import('@codemirror/lang-javascript')).javascript();\n case 'jsx':\n return (await import('@codemirror/lang-javascript')).javascript({ jsx: true });\n case 'typescript':\n return (await import('@codemirror/lang-javascript')).javascript({ typescript: true });\n case 'tsx':\n return (await import('@codemirror/lang-javascript')).javascript({ jsx: true, typescript: true });\n case 'json':\n return (await import('@codemirror/lang-json')).json();\n case 'markdown':\n return (await import('@codemirror/lang-markdown')).markdown();\n case 'html':\n return (await import('@codemirror/lang-html')).html();\n case 'css':\n return (await import('@codemirror/lang-css')).css();\n case 'python':\n return (await import('@codemirror/lang-python')).python();\n case 'yaml':\n return (await import('@codemirror/lang-yaml')).yaml();\n case 'shell':\n return streamMode(async () => (await import('@codemirror/legacy-modes/mode/shell')).shell);\n case 'toml':\n return streamMode(async () => (await import('@codemirror/legacy-modes/mode/toml')).toml);\n case 'dockerfile':\n return streamMode(async () => (await import('@codemirror/legacy-modes/mode/dockerfile')).dockerFile);\n }\n}\n"],"mappings":"AA8BA,MAAM,EAA6D,CACjE,IAAK,aACL,GAAI,aACJ,IAAK,aACL,IAAK,MACL,IAAK,aACL,IAAK,aACL,GAAI,aACJ,IAAK,MACL,KAAM,OACN,MAAO,OACP,SAAU,WACV,GAAI,WACJ,IAAK,OACL,KAAM,OACN,MAAO,OACP,IAAK,MACL,GAAI,SACJ,IAAK,SACL,KAAM,OACN,IAAK,OACL,KAAM,QACN,GAAI,QACJ,IAAK,QACL,KAAM,MACR,EAGM,EAA4D,CAChE,UAAW,QACX,SAAU,QACV,cAAe,aACf,WAAY,YACd,EAGA,SAAS,EAAW,EAA0B,CAC5C,OAAQ,EAAS,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAK,GAAA,CAAI,YAAY,CACxD,CAOA,SAAgB,EAAa,EAA0C,CACrE,IAAM,EAAO,EAAW,CAAQ,EAC1B,EAAQ,EAAoB,GAClC,GAAI,IAAU,IAAA,GAAW,OAAO,EAChC,IAAM,EAAM,EAAK,YAAY,GAAG,EAC5B,OAAM,GACV,OAAO,EAAqB,EAAK,MAAM,EAAM,CAAC,EAChD,CAGA,eAAe,EAAW,EAAgE,CACxF,GAAM,CAAC,CAAE,kBAAkB,GAAU,MAAM,QAAQ,IAAI,CAAC,OAAO,wBAAyB,EAAK,CAAC,CAAC,EAC/F,OAAO,EAAe,OAAO,CAAM,CACrC,CAGA,eAAsB,EAAY,EAAqC,CACrE,OAAQ,EAAR,CACE,IAAK,aACH,OAAQ,MAAM,OAAO,+BAAA,CAAgC,WAAW,EAClE,IAAK,MACH,OAAQ,MAAM,OAAO,+BAAA,CAAgC,WAAW,CAAE,IAAK,EAAK,CAAC,EAC/E,IAAK,aACH,OAAQ,MAAM,OAAO,+BAAA,CAAgC,WAAW,CAAE,WAAY,EAAK,CAAC,EACtF,IAAK,MACH,OAAQ,MAAM,OAAO,+BAAA,CAAgC,WAAW,CAAE,IAAK,GAAM,WAAY,EAAK,CAAC,EACjG,IAAK,OACH,OAAQ,MAAM,OAAO,yBAAA,CAA0B,KAAK,EACtD,IAAK,WACH,OAAQ,MAAM,OAAO,6BAAA,CAA8B,SAAS,EAC9D,IAAK,OACH,OAAQ,MAAM,OAAO,yBAAA,CAA0B,KAAK,EACtD,IAAK,MACH,OAAQ,MAAM,OAAO,wBAAA,CAAyB,IAAI,EACpD,IAAK,SACH,OAAQ,MAAM,OAAO,2BAAA,CAA4B,OAAO,EAC1D,IAAK,OACH,OAAQ,MAAM,OAAO,yBAAA,CAA0B,KAAK,EACtD,IAAK,QACH,OAAO,EAAW,UAAa,MAAM,OAAO,uCAAA,CAAwC,KAAK,EAC3F,IAAK,OACH,OAAO,EAAW,UAAa,MAAM,OAAO,sCAAA,CAAuC,IAAI,EACzF,IAAK,aACH,OAAO,EAAW,UAAa,MAAM,OAAO,4CAAA,CAA6C,UAAU,CACvG,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={"&":{color:`var(--doom-text)`,backgroundColor:`var(--doom-deep)`,fontSize:`12px`,height:`100%`},".cm-scroller":{fontFamily:`var(--doom-font-mono)`,lineHeight:`1.5`},".cm-content":{caretColor:`var(--doom-blue)`,padding:`8px 0`},".cm-cursor, .cm-dropCursor":{borderLeftColor:`var(--doom-blue)`,borderLeftWidth:`2px`},"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":{backgroundColor:`var(--doom-selected)`},".cm-gutters":{backgroundColor:`var(--doom-deep)`,color:`var(--doom-faint)`,borderRight:`1px solid var(--doom-border-soft)`},".cm-activeLine":{backgroundColor:`var(--doom-panel)`},".cm-activeLineGutter":{backgroundColor:`var(--doom-panel)`,color:`var(--doom-dim)`},".cm-foldPlaceholder":{backgroundColor:`var(--doom-panel)`,border:`1px solid var(--doom-border)`,color:`var(--doom-dim)`},".cm-searchMatch":{backgroundColor:`var(--doom-tint-yellow)`,outline:`1px solid var(--doom-edge-yellow)`},".cm-searchMatch.cm-searchMatch-selected":{backgroundColor:`var(--doom-tint-orange)`},".cm-selectionMatch":{backgroundColor:`var(--doom-tint-blue)`},".cm-matchingBracket, &.cm-focused .cm-matchingBracket":{backgroundColor:`var(--doom-tint-green)`,outline:`1px solid var(--doom-edge-green)`},".cm-nonmatchingBracket, &.cm-focused .cm-nonmatchingBracket":{backgroundColor:`var(--doom-tint-red)`},".cm-panels":{backgroundColor:`var(--doom-panel)`,color:`var(--doom-text)`,fontSize:`11px`},".cm-panels.cm-panels-bottom":{borderTop:`1px solid var(--doom-border)`},".cm-panels.cm-panels-top":{borderBottom:`1px solid var(--doom-border)`},".cm-panel input, .cm-panel button, .cm-panel select":{backgroundColor:`var(--doom-deep)`,color:`var(--doom-text)`,border:`1px solid var(--doom-border)`,borderRadius:`2px`,fontFamily:`var(--doom-font-mono)`,fontSize:`11px`},".cm-tooltip":{backgroundColor:`var(--doom-panel)`,border:`1px solid var(--doom-border)`,color:`var(--doom-text)`}},t={comment:{color:`var(--doom-faint)`,fontStyle:`italic`},keyword:{color:`var(--doom-magenta)`},constant:{color:`var(--doom-violet)`},literal:{color:`var(--doom-orange)`},string:{color:`var(--doom-green)`},regexp:{color:`var(--doom-teal)`},operator:{color:`var(--doom-blue)`},punctuation:{color:`var(--doom-dim)`},variable:{color:`var(--doom-text)`},property:{color:`var(--doom-cyan)`},callable:{color:`var(--doom-blue)`},type:{color:`var(--doom-yellow)`},tag:{color:`var(--doom-red)`},attribute:{color:`var(--doom-yellow)`},meta:{color:`var(--doom-faint)`},heading:{color:`var(--doom-hi)`,fontWeight:`bold`},link:{color:`var(--doom-cyan)`,textDecoration:`underline`},emphasis:{fontStyle:`italic`},strong:{fontWeight:`bold`},strikethrough:{textDecoration:`line-through`},invalid:{color:`var(--doom-red)`}};exports.DOOM_EDITOR_STYLES=e,exports.DOOM_SYNTAX_STYLES=t;
|
|
2
|
+
//# sourceMappingURL=editorTheme.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorTheme.cjs","names":[],"sources":["../../../src/lib/editorTheme.ts"],"sourcesContent":["/**\n * The editor's colours, as plain data.\n *\n * Every value is a CSS custom property rather than a resolved colour, which is\n * what lets a theme swap recolour a mounted editor by rewriting `:root`\n * instead of tearing the editor down and rebuilding it. It is also why this is\n * data and not a built CodeMirror extension: nothing here imports an editor,\n * so a caller pays for the styles only inside the chunk that draws them.\n */\n\n/** The chrome: the surface, the gutter, the cursor, the selection, and the search panel. */\nexport const DOOM_EDITOR_STYLES: Readonly<Record<string, Readonly<Record<string, string>>>> = {\n '&': {\n color: 'var(--doom-text)',\n backgroundColor: 'var(--doom-deep)',\n fontSize: '12px',\n height: '100%',\n },\n '.cm-scroller': {\n fontFamily: 'var(--doom-font-mono)',\n lineHeight: '1.5',\n },\n '.cm-content': {\n caretColor: 'var(--doom-blue)',\n padding: '8px 0',\n },\n '.cm-cursor, .cm-dropCursor': {\n borderLeftColor: 'var(--doom-blue)',\n borderLeftWidth: '2px',\n },\n // CodeMirror draws its own selection layer when the editor has focus and\n // leans on the native one when it does not, so both need saying or a\n // selection vanishes the moment a reader clicks the comment box.\n '&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {\n backgroundColor: 'var(--doom-selected)',\n },\n '.cm-gutters': {\n backgroundColor: 'var(--doom-deep)',\n color: 'var(--doom-faint)',\n borderRight: '1px solid var(--doom-border-soft)',\n },\n '.cm-activeLine': {\n backgroundColor: 'var(--doom-panel)',\n },\n '.cm-activeLineGutter': {\n backgroundColor: 'var(--doom-panel)',\n color: 'var(--doom-dim)',\n },\n '.cm-foldPlaceholder': {\n backgroundColor: 'var(--doom-panel)',\n border: '1px solid var(--doom-border)',\n color: 'var(--doom-dim)',\n },\n '.cm-searchMatch': {\n backgroundColor: 'var(--doom-tint-yellow)',\n outline: '1px solid var(--doom-edge-yellow)',\n },\n '.cm-searchMatch.cm-searchMatch-selected': {\n backgroundColor: 'var(--doom-tint-orange)',\n },\n '.cm-selectionMatch': {\n backgroundColor: 'var(--doom-tint-blue)',\n },\n '.cm-matchingBracket, &.cm-focused .cm-matchingBracket': {\n backgroundColor: 'var(--doom-tint-green)',\n outline: '1px solid var(--doom-edge-green)',\n },\n '.cm-nonmatchingBracket, &.cm-focused .cm-nonmatchingBracket': {\n backgroundColor: 'var(--doom-tint-red)',\n },\n '.cm-panels': {\n backgroundColor: 'var(--doom-panel)',\n color: 'var(--doom-text)',\n fontSize: '11px',\n },\n '.cm-panels.cm-panels-bottom': {\n borderTop: '1px solid var(--doom-border)',\n },\n '.cm-panels.cm-panels-top': {\n borderBottom: '1px solid var(--doom-border)',\n },\n '.cm-panel input, .cm-panel button, .cm-panel select': {\n backgroundColor: 'var(--doom-deep)',\n color: 'var(--doom-text)',\n border: '1px solid var(--doom-border)',\n borderRadius: '2px',\n fontFamily: 'var(--doom-font-mono)',\n fontSize: '11px',\n },\n '.cm-tooltip': {\n backgroundColor: 'var(--doom-panel)',\n border: '1px solid var(--doom-border)',\n color: 'var(--doom-text)',\n },\n};\n\n/**\n * The syntax colours, named by what they mark rather than by tag, so the\n * pairing with Lezer's tags stays next to the editor that imports them and\n * this table can be read as a palette.\n */\nexport const DOOM_SYNTAX_STYLES = {\n comment: { color: 'var(--doom-faint)', fontStyle: 'italic' },\n keyword: { color: 'var(--doom-magenta)' },\n constant: { color: 'var(--doom-violet)' },\n literal: { color: 'var(--doom-orange)' },\n string: { color: 'var(--doom-green)' },\n regexp: { color: 'var(--doom-teal)' },\n operator: { color: 'var(--doom-blue)' },\n punctuation: { color: 'var(--doom-dim)' },\n variable: { color: 'var(--doom-text)' },\n property: { color: 'var(--doom-cyan)' },\n callable: { color: 'var(--doom-blue)' },\n type: { color: 'var(--doom-yellow)' },\n tag: { color: 'var(--doom-red)' },\n attribute: { color: 'var(--doom-yellow)' },\n meta: { color: 'var(--doom-faint)' },\n heading: { color: 'var(--doom-hi)', fontWeight: 'bold' },\n link: { color: 'var(--doom-cyan)', textDecoration: 'underline' },\n emphasis: { fontStyle: 'italic' },\n strong: { fontWeight: 'bold' },\n strikethrough: { textDecoration: 'line-through' },\n invalid: { color: 'var(--doom-red)' },\n} as const;\n"],"mappings":"AAWA,MAAa,EAAiF,CAC5F,IAAK,CACH,MAAO,mBACP,gBAAiB,mBACjB,SAAU,OACV,OAAQ,MACV,EACA,eAAgB,CACd,WAAY,wBACZ,WAAY,KACd,EACA,cAAe,CACb,WAAY,mBACZ,QAAS,OACX,EACA,6BAA8B,CAC5B,gBAAiB,mBACjB,gBAAiB,KACnB,EAIA,yFAA0F,CACxF,gBAAiB,sBACnB,EACA,cAAe,CACb,gBAAiB,mBACjB,MAAO,oBACP,YAAa,mCACf,EACA,iBAAkB,CAChB,gBAAiB,mBACnB,EACA,uBAAwB,CACtB,gBAAiB,oBACjB,MAAO,iBACT,EACA,sBAAuB,CACrB,gBAAiB,oBACjB,OAAQ,+BACR,MAAO,iBACT,EACA,kBAAmB,CACjB,gBAAiB,0BACjB,QAAS,mCACX,EACA,0CAA2C,CACzC,gBAAiB,yBACnB,EACA,qBAAsB,CACpB,gBAAiB,uBACnB,EACA,wDAAyD,CACvD,gBAAiB,yBACjB,QAAS,kCACX,EACA,8DAA+D,CAC7D,gBAAiB,sBACnB,EACA,aAAc,CACZ,gBAAiB,oBACjB,MAAO,mBACP,SAAU,MACZ,EACA,8BAA+B,CAC7B,UAAW,8BACb,EACA,2BAA4B,CAC1B,aAAc,8BAChB,EACA,sDAAuD,CACrD,gBAAiB,mBACjB,MAAO,mBACP,OAAQ,+BACR,aAAc,MACd,WAAY,wBACZ,SAAU,MACZ,EACA,cAAe,CACb,gBAAiB,oBACjB,OAAQ,+BACR,MAAO,kBACT,CACF,EAOa,EAAqB,CAChC,QAAS,CAAE,MAAO,oBAAqB,UAAW,QAAS,EAC3D,QAAS,CAAE,MAAO,qBAAsB,EACxC,SAAU,CAAE,MAAO,oBAAqB,EACxC,QAAS,CAAE,MAAO,oBAAqB,EACvC,OAAQ,CAAE,MAAO,mBAAoB,EACrC,OAAQ,CAAE,MAAO,kBAAmB,EACpC,SAAU,CAAE,MAAO,kBAAmB,EACtC,YAAa,CAAE,MAAO,iBAAkB,EACxC,SAAU,CAAE,MAAO,kBAAmB,EACtC,SAAU,CAAE,MAAO,kBAAmB,EACtC,SAAU,CAAE,MAAO,kBAAmB,EACtC,KAAM,CAAE,MAAO,oBAAqB,EACpC,IAAK,CAAE,MAAO,iBAAkB,EAChC,UAAW,CAAE,MAAO,oBAAqB,EACzC,KAAM,CAAE,MAAO,mBAAoB,EACnC,QAAS,CAAE,MAAO,iBAAkB,WAAY,MAAO,EACvD,KAAM,CAAE,MAAO,mBAAoB,eAAgB,WAAY,EAC/D,SAAU,CAAE,UAAW,QAAS,EAChC,OAAQ,CAAE,WAAY,MAAO,EAC7B,cAAe,CAAE,eAAgB,cAAe,EAChD,QAAS,CAAE,MAAO,iBAAkB,CACtC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={"&":{color:`var(--doom-text)`,backgroundColor:`var(--doom-deep)`,fontSize:`12px`,height:`100%`},".cm-scroller":{fontFamily:`var(--doom-font-mono)`,lineHeight:`1.5`},".cm-content":{caretColor:`var(--doom-blue)`,padding:`8px 0`},".cm-cursor, .cm-dropCursor":{borderLeftColor:`var(--doom-blue)`,borderLeftWidth:`2px`},"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":{backgroundColor:`var(--doom-selected)`},".cm-gutters":{backgroundColor:`var(--doom-deep)`,color:`var(--doom-faint)`,borderRight:`1px solid var(--doom-border-soft)`},".cm-activeLine":{backgroundColor:`var(--doom-panel)`},".cm-activeLineGutter":{backgroundColor:`var(--doom-panel)`,color:`var(--doom-dim)`},".cm-foldPlaceholder":{backgroundColor:`var(--doom-panel)`,border:`1px solid var(--doom-border)`,color:`var(--doom-dim)`},".cm-searchMatch":{backgroundColor:`var(--doom-tint-yellow)`,outline:`1px solid var(--doom-edge-yellow)`},".cm-searchMatch.cm-searchMatch-selected":{backgroundColor:`var(--doom-tint-orange)`},".cm-selectionMatch":{backgroundColor:`var(--doom-tint-blue)`},".cm-matchingBracket, &.cm-focused .cm-matchingBracket":{backgroundColor:`var(--doom-tint-green)`,outline:`1px solid var(--doom-edge-green)`},".cm-nonmatchingBracket, &.cm-focused .cm-nonmatchingBracket":{backgroundColor:`var(--doom-tint-red)`},".cm-panels":{backgroundColor:`var(--doom-panel)`,color:`var(--doom-text)`,fontSize:`11px`},".cm-panels.cm-panels-bottom":{borderTop:`1px solid var(--doom-border)`},".cm-panels.cm-panels-top":{borderBottom:`1px solid var(--doom-border)`},".cm-panel input, .cm-panel button, .cm-panel select":{backgroundColor:`var(--doom-deep)`,color:`var(--doom-text)`,border:`1px solid var(--doom-border)`,borderRadius:`2px`,fontFamily:`var(--doom-font-mono)`,fontSize:`11px`},".cm-tooltip":{backgroundColor:`var(--doom-panel)`,border:`1px solid var(--doom-border)`,color:`var(--doom-text)`}},t={comment:{color:`var(--doom-faint)`,fontStyle:`italic`},keyword:{color:`var(--doom-magenta)`},constant:{color:`var(--doom-violet)`},literal:{color:`var(--doom-orange)`},string:{color:`var(--doom-green)`},regexp:{color:`var(--doom-teal)`},operator:{color:`var(--doom-blue)`},punctuation:{color:`var(--doom-dim)`},variable:{color:`var(--doom-text)`},property:{color:`var(--doom-cyan)`},callable:{color:`var(--doom-blue)`},type:{color:`var(--doom-yellow)`},tag:{color:`var(--doom-red)`},attribute:{color:`var(--doom-yellow)`},meta:{color:`var(--doom-faint)`},heading:{color:`var(--doom-hi)`,fontWeight:`bold`},link:{color:`var(--doom-cyan)`,textDecoration:`underline`},emphasis:{fontStyle:`italic`},strong:{fontWeight:`bold`},strikethrough:{textDecoration:`line-through`},invalid:{color:`var(--doom-red)`}};export{e as DOOM_EDITOR_STYLES,t as DOOM_SYNTAX_STYLES};
|
|
2
|
+
//# sourceMappingURL=editorTheme.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorTheme.mjs","names":[],"sources":["../../../src/lib/editorTheme.ts"],"sourcesContent":["/**\n * The editor's colours, as plain data.\n *\n * Every value is a CSS custom property rather than a resolved colour, which is\n * what lets a theme swap recolour a mounted editor by rewriting `:root`\n * instead of tearing the editor down and rebuilding it. It is also why this is\n * data and not a built CodeMirror extension: nothing here imports an editor,\n * so a caller pays for the styles only inside the chunk that draws them.\n */\n\n/** The chrome: the surface, the gutter, the cursor, the selection, and the search panel. */\nexport const DOOM_EDITOR_STYLES: Readonly<Record<string, Readonly<Record<string, string>>>> = {\n '&': {\n color: 'var(--doom-text)',\n backgroundColor: 'var(--doom-deep)',\n fontSize: '12px',\n height: '100%',\n },\n '.cm-scroller': {\n fontFamily: 'var(--doom-font-mono)',\n lineHeight: '1.5',\n },\n '.cm-content': {\n caretColor: 'var(--doom-blue)',\n padding: '8px 0',\n },\n '.cm-cursor, .cm-dropCursor': {\n borderLeftColor: 'var(--doom-blue)',\n borderLeftWidth: '2px',\n },\n // CodeMirror draws its own selection layer when the editor has focus and\n // leans on the native one when it does not, so both need saying or a\n // selection vanishes the moment a reader clicks the comment box.\n '&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {\n backgroundColor: 'var(--doom-selected)',\n },\n '.cm-gutters': {\n backgroundColor: 'var(--doom-deep)',\n color: 'var(--doom-faint)',\n borderRight: '1px solid var(--doom-border-soft)',\n },\n '.cm-activeLine': {\n backgroundColor: 'var(--doom-panel)',\n },\n '.cm-activeLineGutter': {\n backgroundColor: 'var(--doom-panel)',\n color: 'var(--doom-dim)',\n },\n '.cm-foldPlaceholder': {\n backgroundColor: 'var(--doom-panel)',\n border: '1px solid var(--doom-border)',\n color: 'var(--doom-dim)',\n },\n '.cm-searchMatch': {\n backgroundColor: 'var(--doom-tint-yellow)',\n outline: '1px solid var(--doom-edge-yellow)',\n },\n '.cm-searchMatch.cm-searchMatch-selected': {\n backgroundColor: 'var(--doom-tint-orange)',\n },\n '.cm-selectionMatch': {\n backgroundColor: 'var(--doom-tint-blue)',\n },\n '.cm-matchingBracket, &.cm-focused .cm-matchingBracket': {\n backgroundColor: 'var(--doom-tint-green)',\n outline: '1px solid var(--doom-edge-green)',\n },\n '.cm-nonmatchingBracket, &.cm-focused .cm-nonmatchingBracket': {\n backgroundColor: 'var(--doom-tint-red)',\n },\n '.cm-panels': {\n backgroundColor: 'var(--doom-panel)',\n color: 'var(--doom-text)',\n fontSize: '11px',\n },\n '.cm-panels.cm-panels-bottom': {\n borderTop: '1px solid var(--doom-border)',\n },\n '.cm-panels.cm-panels-top': {\n borderBottom: '1px solid var(--doom-border)',\n },\n '.cm-panel input, .cm-panel button, .cm-panel select': {\n backgroundColor: 'var(--doom-deep)',\n color: 'var(--doom-text)',\n border: '1px solid var(--doom-border)',\n borderRadius: '2px',\n fontFamily: 'var(--doom-font-mono)',\n fontSize: '11px',\n },\n '.cm-tooltip': {\n backgroundColor: 'var(--doom-panel)',\n border: '1px solid var(--doom-border)',\n color: 'var(--doom-text)',\n },\n};\n\n/**\n * The syntax colours, named by what they mark rather than by tag, so the\n * pairing with Lezer's tags stays next to the editor that imports them and\n * this table can be read as a palette.\n */\nexport const DOOM_SYNTAX_STYLES = {\n comment: { color: 'var(--doom-faint)', fontStyle: 'italic' },\n keyword: { color: 'var(--doom-magenta)' },\n constant: { color: 'var(--doom-violet)' },\n literal: { color: 'var(--doom-orange)' },\n string: { color: 'var(--doom-green)' },\n regexp: { color: 'var(--doom-teal)' },\n operator: { color: 'var(--doom-blue)' },\n punctuation: { color: 'var(--doom-dim)' },\n variable: { color: 'var(--doom-text)' },\n property: { color: 'var(--doom-cyan)' },\n callable: { color: 'var(--doom-blue)' },\n type: { color: 'var(--doom-yellow)' },\n tag: { color: 'var(--doom-red)' },\n attribute: { color: 'var(--doom-yellow)' },\n meta: { color: 'var(--doom-faint)' },\n heading: { color: 'var(--doom-hi)', fontWeight: 'bold' },\n link: { color: 'var(--doom-cyan)', textDecoration: 'underline' },\n emphasis: { fontStyle: 'italic' },\n strong: { fontWeight: 'bold' },\n strikethrough: { textDecoration: 'line-through' },\n invalid: { color: 'var(--doom-red)' },\n} as const;\n"],"mappings":"AAWA,MAAa,EAAiF,CAC5F,IAAK,CACH,MAAO,mBACP,gBAAiB,mBACjB,SAAU,OACV,OAAQ,MACV,EACA,eAAgB,CACd,WAAY,wBACZ,WAAY,KACd,EACA,cAAe,CACb,WAAY,mBACZ,QAAS,OACX,EACA,6BAA8B,CAC5B,gBAAiB,mBACjB,gBAAiB,KACnB,EAIA,yFAA0F,CACxF,gBAAiB,sBACnB,EACA,cAAe,CACb,gBAAiB,mBACjB,MAAO,oBACP,YAAa,mCACf,EACA,iBAAkB,CAChB,gBAAiB,mBACnB,EACA,uBAAwB,CACtB,gBAAiB,oBACjB,MAAO,iBACT,EACA,sBAAuB,CACrB,gBAAiB,oBACjB,OAAQ,+BACR,MAAO,iBACT,EACA,kBAAmB,CACjB,gBAAiB,0BACjB,QAAS,mCACX,EACA,0CAA2C,CACzC,gBAAiB,yBACnB,EACA,qBAAsB,CACpB,gBAAiB,uBACnB,EACA,wDAAyD,CACvD,gBAAiB,yBACjB,QAAS,kCACX,EACA,8DAA+D,CAC7D,gBAAiB,sBACnB,EACA,aAAc,CACZ,gBAAiB,oBACjB,MAAO,mBACP,SAAU,MACZ,EACA,8BAA+B,CAC7B,UAAW,8BACb,EACA,2BAA4B,CAC1B,aAAc,8BAChB,EACA,sDAAuD,CACrD,gBAAiB,mBACjB,MAAO,mBACP,OAAQ,+BACR,aAAc,MACd,WAAY,wBACZ,SAAU,MACZ,EACA,cAAe,CACb,gBAAiB,oBACjB,OAAQ,+BACR,MAAO,kBACT,CACF,EAOa,EAAqB,CAChC,QAAS,CAAE,MAAO,oBAAqB,UAAW,QAAS,EAC3D,QAAS,CAAE,MAAO,qBAAsB,EACxC,SAAU,CAAE,MAAO,oBAAqB,EACxC,QAAS,CAAE,MAAO,oBAAqB,EACvC,OAAQ,CAAE,MAAO,mBAAoB,EACrC,OAAQ,CAAE,MAAO,kBAAmB,EACpC,SAAU,CAAE,MAAO,kBAAmB,EACtC,YAAa,CAAE,MAAO,iBAAkB,EACxC,SAAU,CAAE,MAAO,kBAAmB,EACtC,SAAU,CAAE,MAAO,kBAAmB,EACtC,SAAU,CAAE,MAAO,kBAAmB,EACtC,KAAM,CAAE,MAAO,oBAAqB,EACpC,IAAK,CAAE,MAAO,iBAAkB,EAChC,UAAW,CAAE,MAAO,oBAAqB,EACzC,KAAM,CAAE,MAAO,mBAAoB,EACnC,QAAS,CAAE,MAAO,iBAAkB,WAAY,MAAO,EACvD,KAAM,CAAE,MAAO,mBAAoB,eAAgB,WAAY,EAC/D,SAAU,CAAE,UAAW,QAAS,EAChC,OAAQ,CAAE,WAAY,MAAO,EAC7B,cAAe,CAAE,eAAgB,cAAe,EAChD,QAAS,CAAE,MAAO,iBAAkB,CACtC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={avif:`image`,bmp:`image`,gif:`image`,ico:`image`,jpeg:`image`,jpg:`image`,png:`image`,svg:`image`,webp:`image`,m4v:`video`,mov:`video`,mp4:`video`,webm:`video`,pdf:`pdf`};function t(e){let t=e.split(`/`).at(-1)??``,n=t.lastIndexOf(`.`);return n<1?``:t.slice(n+1).toLowerCase()}function n(n){return e[t(n)]??`download`}exports.mediaKindOf=n;
|
|
2
|
+
//# sourceMappingURL=media.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.cjs","names":[],"sources":["../../../src/lib/media.ts"],"sourcesContent":["import type { MediaKind } from '../types/editor.ts';\n\n/**\n * Which files a browser can show without help.\n *\n * Keyed by lower-case extension without the dot, and deliberately short: an\n * entry here is a promise that the element named by its kind will render the\n * bytes, so a format the browser only sometimes handles belongs in the\n * download fallback instead of on this list.\n */\nconst MEDIA_KIND_BY_EXTENSION: Readonly<Record<string, MediaKind>> = {\n avif: 'image',\n bmp: 'image',\n gif: 'image',\n ico: 'image',\n jpeg: 'image',\n jpg: 'image',\n png: 'image',\n svg: 'image',\n webp: 'image',\n m4v: 'video',\n mov: 'video',\n mp4: 'video',\n webm: 'video',\n pdf: 'pdf',\n};\n\n/** The extension of a path, lower-cased and without the dot; empty when it has none. */\nfunction extensionOf(filePath: string): string {\n const name = filePath.split('/').at(-1) ?? '';\n const dot = name.lastIndexOf('.');\n // A leading dot is the whole name of a dotfile, not the start of a suffix.\n return dot < 1 ? '' : name.slice(dot + 1).toLowerCase();\n}\n\n/**\n * How to show the file at this path. Anything unrecognised is a download,\n * which is the honest answer for a `.docx` or a `.zip`: a browser cannot\n * render it, and pretending otherwise costs a converter that loses the\n * formatting it converted.\n */\nexport function mediaKindOf(filePath: string): MediaKind {\n return MEDIA_KIND_BY_EXTENSION[extensionOf(filePath)] ?? 'download';\n}\n"],"mappings":"AAUA,MAAM,EAA+D,CACnE,KAAM,QACN,IAAK,QACL,IAAK,QACL,IAAK,QACL,KAAM,QACN,IAAK,QACL,IAAK,QACL,IAAK,QACL,KAAM,QACN,IAAK,QACL,IAAK,QACL,IAAK,QACL,KAAM,QACN,IAAK,KACP,EAGA,SAAS,EAAY,EAA0B,CAC7C,IAAM,EAAO,EAAS,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAK,GACrC,EAAM,EAAK,YAAY,GAAG,EAEhC,OAAO,EAAM,EAAI,GAAK,EAAK,MAAM,EAAM,CAAC,CAAC,CAAC,YAAY,CACxD,CAQA,SAAgB,EAAY,EAA6B,CACvD,OAAO,EAAwB,EAAY,CAAQ,IAAM,UAC3D"}
|