kireji 0.7.3 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +4 -4
  2. package/package.json +1 -1
  3. package/src/app/kireji/description +1 -1
  4. package/src/app/kireji/editor/sections/state-space/part.html_.js +5 -5
  5. package/src/app/kireji/editor/static.css +7 -0
  6. package/src/app/kireji/editor/tab-group/mathML-subpart.js +8 -0
  7. package/src/app/kireji/sidebar/static.css +51 -15
  8. package/src/app/kireji/static.css +0 -4
  9. package/src/app/kireji/tool-bar/part.css +1 -1
  10. package/src/application-goto.js +8 -5
  11. package/src/build.js +89 -13
  12. package/src/kireji.schema.json +205 -0
  13. package/src/part.css_.js +20 -0
  14. package/src/part.html_.js +20 -8
  15. package/src/parts/abstract/clip/mathML-subpart.js +4 -0
  16. package/src/parts/abstract/match/mathML-subpart.js +9 -0
  17. package/src/parts/abstract/mesh/data-get.js +11 -0
  18. package/src/parts/abstract/mesh/mathML-subpart.js +10 -0
  19. package/src/parts/abstract/mesh/ray-cast.js +4 -4
  20. package/src/parts/abstract/mesh/type.d.ts +10 -0
  21. package/src/parts/abstract/mix/mathML-subpart.js +9 -0
  22. package/src/parts/abstract/part/mathML-subpart.js +3 -0
  23. package/src/parts/abstract/part/mathML.js +22 -0
  24. package/src/parts/abstract/part/part.json +11 -0
  25. package/src/parts/abstract/part/type.d.ts +4 -0
  26. package/src/parts/abstract/part-mask/mathML-subpart.js +1 -0
  27. package/src/parts/abstract/part-outliner/itemHTML-recursive.js +1 -1
  28. package/src/parts/abstract/part.json +1 -1
  29. package/src/parts/abstract/permutation/mathML-subpart.js +10 -0
  30. package/src/parts/abstract/scroller/mathML-subpart.js +1 -0
  31. package/src/parts/abstract/scroller/onscroll.js +3 -1
  32. package/src/parts/abstract/scroller/point-thumb.js +1 -1
  33. package/src/parts/core/client/async-install.js +1 -1
  34. package/src/parts/core/part.json +1 -1
  35. package/src/parts/core/server/sync-install.js +1 -1
  36. package/src/parts/core/worker/async-take-control.js +1 -1
  37. package/src/parts/desktop/era/modern/part.css +5 -1
  38. package/src/parts/desktop/era/vintage/static.css +5 -1
  39. package/src/parts/desktop/task-bar/menu/menu.html_.js +23 -12
  40. package/src/parts/desktop/task-bar/part.html_.js +3 -1
  41. package/src/parts/desktop/task-bar/view-hydrate.js +1 -1
  42. package/src/parts/desktop/type.d.ts +5 -5
  43. package/src/parts/desktop/windows/point.js +1 -1
  44. package/src/parts/desktop/windows/superset-get.js +1 -1
  45. package/src/{part.css → static.css} +1 -10
  46. package/src/type.d.ts +172 -10
  47. package/src/validate.js +3 -3
  48. package/src/app/kireji/editor/tab-group/equation.html_.js +0 -42
  49. package/src/parts/abstract/boolean/equation-variable.html +0 -1
  50. package/src/parts/abstract/box/build.js +0 -24
  51. package/src/parts/abstract/box/constants.js +0 -1
  52. package/src/parts/abstract/box/description-abstract +0 -1
  53. package/src/parts/abstract/box/dimensions_.js +0 -1
  54. package/src/parts/abstract/box/equation.html_.js +0 -1
  55. package/src/parts/abstract/box/model_.js +0 -1
  56. package/src/parts/abstract/box/part.json +0 -3
  57. package/src/parts/abstract/box/routeID-distribute.js +0 -7
  58. package/src/parts/abstract/box/routeID-model-to.js +0 -18
  59. package/src/parts/abstract/box/title-abstract +0 -1
  60. package/src/parts/abstract/box/type.d.ts +0 -20
  61. package/src/parts/abstract/match/equation.html_.js +0 -11
  62. package/src/parts/abstract/mix/equation.html_.js +0 -11
  63. package/src/parts/abstract/part/equation-variable.html_.js +0 -1
  64. package/src/parts/abstract/part/equation.html_.js +0 -3
  65. package/src/parts/abstract/part-mask/equation-variable.html_.js +0 -1
  66. package/src/parts/abstract/part-mask/equation.html_.js +0 -1
  67. package/src/parts/abstract/permutation/equation.html_.js +0 -1
  68. package/src/parts/abstract/scroller/equation-variable.html +0 -1
  69. package/src/parts/abstract/scroller/equation.html +0 -1
  70. package/src/parts/user/part.json +0 -3
  71. package/src/parts/user/title +0 -1
  72. package/src/parts/user/type.d.ts +0 -2
@@ -0,0 +1,4 @@
1
+ if (DEPTH <= 0)
2
+ return [/* xml */`<mi>frames</mi><mo>(</mo><msub><mi>𝑝</mi><mi>${clip.key}</mi></msub><mo>)</mo>`]
3
+
4
+ return [`<mn>${clip.cardinality}</mn>`]
@@ -0,0 +1,9 @@
1
+ const defaultTerm = /* xml */`<mn>1</mn>`
2
+
3
+ if (DEPTH <= 0 || part.length === 0)
4
+ // Strip the "<math>" tags off.
5
+ return [match.length ? /* xml */`<mo largeop="true">∑</mo><msub><mi>𝑘</mi><msub><mi>𝑝</mi><mi>${part.key ?? "ecosystem"}</mi></msub></msub>` : defaultTerm]
6
+
7
+ const operator = "<mo>+</mo>"
8
+ const addends = part.map(addend => addend.mathML(DEPTH - 1, "none", LABELS, true, false))
9
+ return addends.length ? addends.flatMap(addend => [addend, operator]).slice(0, -1) : [defaultTerm]
@@ -0,0 +1,11 @@
1
+ const { points, tris } = mesh.manifest
2
+
3
+ const data = [[], []]
4
+
5
+ for (let index = 0; index < points.length; index += 2)
6
+ data[0].push([points[index], points[index + 1]])
7
+
8
+ for (let index = 0; index < tris.length; index += 3)
9
+ data[1].push([tris[index], tris[index + 1], tris[index + 2]])
10
+
11
+ return data
@@ -0,0 +1,10 @@
1
+ if (DEPTH <= 0)
2
+ return [
3
+ `<munder><mo>∑</mo><mrow><mi>t</mi><mo>∈</mo><mi>tris</mi><mo>(</mo><msub><mi>𝑝</mi><mi>${mesh.key}</mi></msub><mo>)</mo></mrow></munder>`,
4
+ `<munder><mo>∑</mo><mrow><mi>r</mi><mo>∈</mo><mi>rows</mi><mo>(</mo><mi>t</mi><mo>)</mo></mrow></munder>`,
5
+ `<msub><mi>𝑘</mi><mi>r</mi></msub>`
6
+ ]
7
+
8
+ return /*mesh.triTable.length > 20 ? base(DEPTH) :*/ mesh.triTable.flatMap(triData => {
9
+ return [`<mn>${triData.cardinality}</mn>`, "<mo>+</mo>"]
10
+ }).slice(0, -1)
@@ -20,7 +20,7 @@ const timeBetweenIntersections = { ...timeOfNextIntersection }
20
20
  // Set the clock to zero.
21
21
  let time = 0
22
22
 
23
- function initalizeRayIntersectionSchedule(alsoComputeIntersectionInterval) {
23
+ function initializeRayIntersectionSchedule(alsoComputeIntersectionInterval) {
24
24
 
25
25
  // If the force vector isn't parallel to the x axis...
26
26
  if (FORCE_VECTOR.x !== 0) {
@@ -45,7 +45,7 @@ function initalizeRayIntersectionSchedule(alsoComputeIntersectionInterval) {
45
45
  }
46
46
  }
47
47
 
48
- initalizeRayIntersectionSchedule(true)
48
+ initializeRayIntersectionSchedule(true)
49
49
 
50
50
  const start = _.now
51
51
 
@@ -160,7 +160,7 @@ while (true) {
160
160
  }
161
161
 
162
162
  if (boundaryAppearsFlat) {
163
- // TODO: Consider using the line through the opposing neighbors to search for assymetry in the mesh boundry.
163
+ // TODO: Consider using the line through the opposing neighbors to search for asymmetry in the mesh boundary.
164
164
  }
165
165
 
166
166
  // If there is no neighboring point, we are "stuck". The ray cast ends here.
@@ -232,7 +232,7 @@ while (true) {
232
232
  safeIterationResult.forceVector = FORCE_VECTOR
233
233
 
234
234
  // The normal ray intersection schedule has changed.
235
- initalizeRayIntersectionSchedule()
235
+ initializeRayIntersectionSchedule()
236
236
 
237
237
  // Proceed with normal ray casting behavior from this point.
238
238
  continue
@@ -26,6 +26,7 @@ declare interface IMesh<TOwner>
26
26
  readonly triIndex?: IMeshTriIndex
27
27
  /** The current position of the state in the mesh. */
28
28
  readonly position: IVector2
29
+ readonly manifest: IMeshManifest
29
30
  }
30
31
 
31
32
  declare interface IMeshTriData {
@@ -60,6 +61,15 @@ declare interface IMeshTriDataRow {
60
61
  readonly offset: bigint
61
62
  }
62
63
 
64
+
65
+ declare interface IMeshManifest
66
+ extends IPartManifest {
67
+ /** The available collision vertices as a flat array of 2D coordinates. Used for defining the world's collision tris. */
68
+ readonly points: number[],
69
+ /** The list of collision tris, as a flat array of point triples. Used to define the walkable area of the world. */
70
+ readonly tris: number[]
71
+ }
72
+
63
73
  declare type IMeshData = [IMeshPoint[], IMeshTri[]]
64
74
 
65
75
  declare type IMeshTri =
@@ -0,0 +1,9 @@
1
+ const defaultTerm = /* xml */`<mn>1</mn>`
2
+
3
+ if (DEPTH <= 0 || part.length === 0)
4
+ // Strip the "<math>" tags off.
5
+ return [mix.length ? /* xml */`<mo largeop="true">∏</mo><msub><mi>𝑘</mi><msub><mi>𝑝</mi><mi>${part.key ?? "ecosystem"}</mi></msub></msub>` : defaultTerm]
6
+
7
+ const operator = "<mo class=product>&sdot;</mo>"
8
+ const factors = part.map(subpart => subpart.mathML(DEPTH - 1, "none", LABELS, true, false)).filter(mathML => mathML !== defaultTerm && mathML !== `<mrow>${defaultTerm}</mrow>`)
9
+ return factors.length ? factors.flatMap(factor => [factor, operator]).slice(0, -1) : [defaultTerm]
@@ -0,0 +1,3 @@
1
+ const cardinality = part.cardinality
2
+ const cardinalityAsString = instances.includes(part) ? cardinality.toString() : null
3
+ return [cardinalityAsString.length < 16 ? `<mn>${cardinalityAsString}</mn>` : scientific(cardinality, true).slice(6, -7).split("<mo>&sdot;</mo>").flatMap(term => [term, "<mo>&sdot;</mo>"]).slice(0, -1)]
@@ -0,0 +1,22 @@
1
+ const equationVariable = EQUATION_TYPE === "variable" || EQUATION_TYPE === "both" ? `${recurse(0, "none", false, false)}<mo>=</mo>` : ""
2
+ const equationValue = EQUATION_TYPE === "value" || EQUATION_TYPE === "both" ? `<mo>=</mo>${part.cardinality.toString().length <= 15 ? `<mn>${part.cardinality}</mn>` : `<mrow>${scientific(part.cardinality, true).slice(6, -7)}</mrow>`}` : ""
3
+ const expression = (() => {
4
+
5
+ if (DEPTH <= 0)
6
+ return `<msub><mi>𝑘</mi><mi>${part.key ?? "ecosystem"}</mi></msub>`
7
+
8
+ const terms = part.subpartMathML(DEPTH - 1, LABELS)
9
+
10
+ const needsParentheses = PARENTHESIZE && terms.length > 1
11
+
12
+ debug(terms)
13
+
14
+ // Allow "<mrow>" tag nesting for parentheses.
15
+ return (LABELS ? "<munder>" + (needsParentheses ? "" : "<mrow>") : "") + (needsParentheses ? "<mrow class=parenthetic><mo>(</mo>" : "") + terms.join("") + (needsParentheses ? `<mo>)</mo></mrow>` : "") + (LABELS ? (needsParentheses ? "" : "</mrow>") + `<munder><mo stretchy="true">&#x23df;</mo>${recurse(0, "none", false, false)}</munder></munder>` : "")
16
+ })()
17
+
18
+ // TODO: handle parenthesis!
19
+
20
+ const showBracketBelow = DEPTH > 2
21
+
22
+ return /* html */`${WRAP_IN_MATH_TAG ? "<math displaystyle=true><mrow>" : ""}${equationVariable}${expression}${equationValue}${WRAP_IN_MATH_TAG ? "</mrow></math>" : ""}`
@@ -75,6 +75,17 @@
75
75
  ],
76
76
  "manifest-resolve-part-from": [
77
77
  "PROPERTY_KEY"
78
+ ],
79
+ "mathML": [
80
+ "DEPTH = 0",
81
+ "EQUATION_TYPE = \"none\"",
82
+ "LABELS = false",
83
+ "PARENTHESIZE = false",
84
+ "WRAP_IN_MATH_TAG = true"
85
+ ],
86
+ "mathML-subpart": [
87
+ "DEPTH",
88
+ "LABELS"
78
89
  ]
79
90
  }
80
91
  }
@@ -109,6 +109,10 @@ declare interface IPart<TOwner, TSubpart>
109
109
  readonly resolveOwnerOfManifest(PROPERTY_KEY: string): IPartAny | null
110
110
  /** Returns a part whose host was provided as a (potentially relative) host name using the given property key in the part's manifest. This method uses the nearest part on which the manifest key is actually defined as the base for resolving any relative host name. Returns null if the given property does not exist anywhere in the chain. */
111
111
  readonly resolvePartFromManifest(PROPERTY_KEY: string): IPartAny | null
112
+ /** Generates a returns a MathML string that depicts the cardinality equation of the platform. @param DEPTH the number of levels deep to expand the terms of the equation (up to Infinity) @param AS_EQUATION when true, begins the expression with something like `<math><msub><mi>k</mi><mi>part key</mi></msub><mo>=</mo>...` @param PARENTHESIZE whether or not to add parenthesis around the expression (useful when it will be nested in a larger one) (they will only be added if the resulting expression is not a single term). */
113
+ readonly mathML(DEPTH: number = 0, EQUATION_TYPE: string = "none", LABELS: boolean = false, PARENTHESIZE: boolean = false, WRAP_IN_MATH_TAG: boolean = true): string
114
+ /** Returns an array of string terms and operators which, when joined, depict the part's cardinality collecting arithmetic. */
115
+ readonly subpartMathML(DEPTH: number, LABELS: boolean): string[]
112
116
 
113
117
  // Runtime Properties.
114
118
  /** The parent part.
@@ -0,0 +1 @@
1
+ return [/* xml */`<msup><mn>2</mn><mn>${partMask.superset.length}</mn></msup>`]
@@ -6,7 +6,7 @@ return partOutliner.getChildren(SUBJECT).map((childPart, i, childArray) => {
6
6
  const symbol = `<img src="${childPart.placeholderImage("part.png")}"/>`
7
7
  const handle = hasSubparts ? `<svg ${partOutliner.pointAttr("togglePoint", folderIndex)} xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 2 2" class="explore-toggle"><line x1="-0.41" y1="0" x2="0.41" y2="0" stroke-width="0.2" stroke-linecap="round" />${isOpen ? "" : `<line x1="0" y1="-0.41" x2="0" y2="0.41" stroke-width="0.2" stroke-linecap="round" />`}</svg>` : ""
8
8
  const label = `<span class="label${childPart.isAbstract ? " abstract" : ""}">${partOutliner.getLabel(childPart)}</span>`
9
- const summary = `<summary ${partOutliner.pointAttr("point", partIndex)} data-index="${partIndex}"${partOutliner.isActive(childPart) ? " data-active" : ""}${IS_LAST_OF_TYPE && !hasSubparts ? ' id="lastOutlinerItem"' : ""}>${Array(DEPTH + +!hasSubparts).fill('<outliner-spacer></outliner-spacer>').join("")}${handle}${symbol}${label}</summary>`
9
+ const summary = `<summary ${partOutliner.pointAttr("point", partIndex)} data-index="${partIndex}"${partOutliner.isActive(childPart) ? " data-active" : ""}${IS_LAST_OF_TYPE && !hasSubparts ? ' id="lastOutlinerItem"' : ""}><outliner-spacer style="--depth:${DEPTH + +!hasSubparts}"></outliner-spacer>${handle}${symbol}${label}</summary>`
10
10
  return `<details${hasSubparts ? "" : ` class=empty`} ${isOpen ? "open" : ""}>${summary}${recurse(childPart, DEPTH + 1, IS_LAST_OF_TYPE && i === childArray.length - 1)}</details>`
11
11
  }).join("")
12
12
 
@@ -1,3 +1,3 @@
1
1
  {
2
- "extends": "coming-soon"
2
+ "extends": "mix"
3
3
  }
@@ -0,0 +1,10 @@
1
+ const n = permutation.supersetSize
2
+
3
+ // TODO: factor in other aspects when expanding to the collection type.
4
+
5
+ return [
6
+ "<mn>1</mn>",
7
+ "<mo>+</mo>",
8
+ `<munderover><mo>∑</mo><mrow><mi>𝑛</mi><mo>=</mo><mn>1</mn></mrow><mi>${n}</mi></munderover>`,
9
+ `<munderover><mo>∏</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>𝑛</mi></mrow></munderover><mrow><mn>${permutation.payloadCardinality}</mn><mo>(</mo><mi>${n}</mi><mo>-</mo><mi>i</mi><mo>+</mo><mn>1</mn><mo>)</mo></mrow>`
10
+ ]
@@ -0,0 +1 @@
1
+ return [`<msup><mn>10</mn><mn>4</mn></msup>`]
@@ -1,4 +1,6 @@
1
- if (scroller.skipRouteIDUpdate) {
1
+ if (scroller.skipRouteIDUpdate || !client.hydrated) {
2
+ if (!client.hydrated)
3
+ debug('onscroll from within the hydration phase')
2
4
  scroller.skipRouteIDUpdate = false
3
5
  } else {
4
6
  const maxY = scroller.container.scrollHeight
@@ -4,7 +4,7 @@ const rangeLimit = BigInt(Math.trunc(Number(scrollerLimit) * (1 - scroller.conta
4
4
 
5
5
  pointer.handle({
6
6
  drag(pointerEvent) {
7
- const positionalRouteID = markedRouteID + BigInt(Math.trunc((pointerEvent.clientY - POINTER_EVENT.clientY) / (scroller.scrollBar.clientHeight - (era.arm === era.vintage ? 2 * scroller.scrollBar.clientWidth : 0)) * Number(scrollerLimit)))
7
+ const positionalRouteID = markedRouteID + BigInt(Math.trunc((pointerEvent.clientY - POINTER_EVENT.clientY) / (scroller.scrollBar.clientHeight - (era && era.arm === era.vintage ? 2 * scroller.scrollBar.clientWidth : 0)) * Number(scrollerLimit)))
8
8
  const newRouteID = positionalRouteID < 0n ? 0n : (positionalRouteID > rangeLimit) ? rangeLimit : positionalRouteID
9
9
  if (newRouteID !== scroller.routeID) scroller.setRouteID(newRouteID)
10
10
  },
@@ -6,7 +6,7 @@ await Promise.all([
6
6
  if (!production) {
7
7
 
8
8
  // To debug FOUC.
9
- if (+_.haltHydration) {
9
+ if (_.haltHydration === "enabled") {
10
10
  warn('Intentionally blocked hydration.')
11
11
  return
12
12
  }
@@ -1,3 +1,3 @@
1
1
  {
2
- "extends": "coming-soon"
2
+ "extends": "mix"
3
3
  }
@@ -107,7 +107,7 @@ logScope(1, `\nCreating Deployment Artifact`, log => {
107
107
  })
108
108
 
109
109
  logScope(1, `\nDeployment Artifact Stats`, () => {
110
- logStringSize(1, preHydrationArchive)
110
+ logStringSize(1, _.preHydrationArchive)
111
111
  })
112
112
 
113
113
  const httpServer = require('http').createServer((request, response) => logServerScope(
@@ -19,7 +19,7 @@ await logScope(1, 'Ensuring ServiceWorker Controller', async log => {
19
19
 
20
20
  if (!production) {
21
21
  nav.serviceWorker.oncontrollerchange = () => {
22
- if (+_.resetLocalState) {
22
+ if (_.resetLocalState === "enabled") {
23
23
  /* Reset to the landing hash on service worker update (useful during
24
24
  development that changes the part arrangement frequently. */
25
25
  location.assign(location.origin + `/${_.version}/`)
@@ -3,13 +3,17 @@ body {
3
3
  --bottom-shadow: 0 2px 7px #0002;
4
4
  --icon-size: 29px;
5
5
  --spacing: 14px;
6
- --task-bar-height: calc(var(--icon-size) + 2 * var(--spacing));
7
6
  --title-bar-icon-size: 22px;
8
7
  --title-bar-height: calc(var(--title-bar-icon-size) + var(--spacing));
9
8
  --default-font-size: 13px;
10
9
  font: var(--default-font-size) var(--system-ui);
11
10
  }
12
11
 
12
+ body,
13
+ task-bar {
14
+ --task-bar-height: calc(var(--icon-size) + 2 * var(--spacing));
15
+ }
16
+
13
17
  title-bar {
14
18
  --icon-size: var(--title-bar-icon-size);
15
19
  box-shadow: inset 0 0 0 1px var(--bg-un-mode);
@@ -172,7 +172,6 @@ scroll-bar>thumb- {
172
172
  body {
173
173
  --bottom: calc(var(--task-bar-height) - 4px);
174
174
  --spacing: 12px;
175
- --task-bar-height: 28px;
176
175
  --title-bar-height: 18px;
177
176
  --icon-size: var(--task-bar-height);
178
177
  --deep-inset:
@@ -194,6 +193,11 @@ body {
194
193
  image-rendering: pixelated;
195
194
  }
196
195
 
196
+ body,
197
+ task-bar {
198
+ --task-bar-height: 28px;
199
+ }
200
+
197
201
  body.dark {
198
202
  --deep-inset:
199
203
  inset -1px -1px var(--bg-light-est),
@@ -1,18 +1,29 @@
1
- return `<task-menu style="${menu.arm.style}">
2
- <ul id=application-control>${Object.entries(_.menuApplications).map(([host, application]) => {
3
- const isCurrentApplication = application === _.application
4
- return `
1
+ const
2
+ controls = [],
3
+ sections = []
4
+
5
+ if (_.includeUpdates === "full" || (!production && _.includeUpdates === "local-only"))
6
+ controls.push(update["part.html"])
7
+
8
+ if (_.includeColor === "full" || (!production && _.includeColor.startsWith("debug-")))
9
+ controls.push(color["part.html"])
10
+
11
+ if (_.includeEra === "full" || (!production && _.includeEra.startsWith("debug-")))
12
+ controls.push(era["part.html"])
13
+
14
+ if (_.includeMenuApps === "full" || (!production && _.includeMenuApps === "local-only"))
15
+ sections.push(`<ul id=application-control>${Object.entries(_.menuApplications).map(([host, application]) => {
16
+ const isCurrentApplication = application === _.application
17
+ return `
5
18
  <li class=task-link${isCurrentApplication ? ` data-here` : ""}>
6
19
  <a ${isCurrentApplication ? "" : _.pointAttr()} href=https://${host}>
7
20
  <img src="${application.placeholderImage("part.png")}" class=part-icon />
8
21
  <span class=label>${application.titleMenu ?? application.title}</span>
9
22
  </a>
10
23
  </li>`
11
- }).join("")}</ul>
12
- <hr>
13
- <section id="settings">
14
- ${update["part.html"]}
15
- ${color["part.html"]}
16
- ${era["part.html"]}
17
- </section>
18
- </task-menu>`
24
+ }).join("")}</ul>`)
25
+
26
+ if (controls.length)
27
+ sections.push(`\n <hr>\n <section id="settings">${controls.join(`\n `)}</section>`)
28
+
29
+ return `<task-menu style="${menu.arm.style}">${sections.join(`\n `)}</task-menu>`
@@ -1 +1,3 @@
1
- return `<task-bar tabIndex=0>${taskBar.menu["part.html"]}${windows.instances.map((window, index) => windows.renderTaskHTML(window, index)).join("")}<flex-spacer></flex-spacer>${taskBar.tray["part.html"]}</task-bar>`
1
+ const includeDesktop = _.includeDesktop === "demo" || (!production && (_.includeDesktop === "full" || _.includeDesktop === "local-only"))
2
+
3
+ return `<task-bar tabIndex=0>${taskBar.menu["part.html"]}${includeDesktop ? windows.instances.map((window, index) => windows.renderTaskHTML(window, index)).join("") : ""}<flex-spacer></flex-spacer>${includeDesktop ? taskBar.tray["part.html"] : ""}</task-bar>`
@@ -5,7 +5,7 @@ client.promise.then(() => {
5
5
  if (taskBar.menu.arm !== taskBar.menu.closed)
6
6
  Q("task-bar>button.menu").focus()
7
7
  else
8
- Q("title-bar").focus()
8
+ Q("title-bar")?.focus()
9
9
 
10
10
  document.addEventListener('pointerdown', pointerEvent => {
11
11
  if (taskBar.menu.arm !== taskBar.menu.closed && !inRect(pointerEvent, taskBar.menu.element.getBoundingClientRect())) {
@@ -2,11 +2,11 @@ declare interface IDesktop
2
2
  extends IPartsApplication {
3
3
 
4
4
  // Subparts.
5
- readonly color: IColor
6
- readonly era: IEra
7
- readonly taskBar: ITaskBar
8
- readonly icons: IDesktopIcons
9
- readonly windows: IDesktopWindows
5
+ readonly color?: IColor
6
+ readonly era?: IEra
7
+ readonly taskBar?: ITaskBar
8
+ readonly icons?: IDesktopIcons
9
+ readonly windows?: IDesktopWindows
10
10
  }
11
11
 
12
12
  declare const desktop: IDesktop
@@ -3,7 +3,7 @@ pointer.handle({
3
3
  const window = windows.instances[INSTANCE_INDEX]
4
4
  if (_.application === window.application) {
5
5
  const focusElement = Q(`body>:not(task-bar):focus-within, body>task-bar>button.task.pressed:focus`)
6
- if (focusElement && desktop.era.arm === desktop.era.vintage)
6
+ if (focusElement && desktop.era && desktop.era.arm === desktop.era.vintage)
7
7
  _.gotoApplication("desktop.parts")
8
8
  else TARGET_ELEMENT.focus()
9
9
  } else _.gotoApplication(window.application.host)
@@ -1 +1 @@
1
- return Object.values(_.applications)
1
+ return Object.values(_.applications).filter(application => application !== _.parts.desktop)
@@ -30,7 +30,6 @@ body {
30
30
  --system-ui-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Consolas", "Courier New", monospace;
31
31
  --menu-tween: 0;
32
32
  --h: 100vh;
33
- --warning-height: 28px;
34
33
  --wallpaper-height: calc(var(--h) - var(--task-bar-height) - var(--warning-height) - var(--title-bar-height));
35
34
  --wallpaper-width: 100vw;
36
35
  --padding: calc(3.5 * var(--spacing));
@@ -292,15 +291,6 @@ body.dark warning- {
292
291
  background-color: #644c08;
293
292
  }
294
293
 
295
- @media (width < 390px) {
296
-
297
- html,
298
- body {
299
- --warning-height: 49px;
300
- }
301
- }
302
-
303
-
304
294
  #fullscreen-tray-item,
305
295
  #share-tray-item {
306
296
  display: none !important;
@@ -311,6 +301,7 @@ body.dark warning- {
311
301
  font-size: revert;
312
302
  }
313
303
 
304
+ /* TODO: Make title-bar and other desktop experience css dynamic (because it can be disabled in the config). */
314
305
  title-bar {
315
306
  display: flex;
316
307
  flex-flow: row nowrap;