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.
- package/README.md +4 -4
- package/package.json +1 -1
- package/src/app/kireji/description +1 -1
- package/src/app/kireji/editor/sections/state-space/part.html_.js +5 -5
- package/src/app/kireji/editor/static.css +7 -0
- package/src/app/kireji/editor/tab-group/mathML-subpart.js +8 -0
- package/src/app/kireji/sidebar/static.css +51 -15
- package/src/app/kireji/static.css +0 -4
- package/src/app/kireji/tool-bar/part.css +1 -1
- package/src/application-goto.js +8 -5
- package/src/build.js +89 -13
- package/src/kireji.schema.json +205 -0
- package/src/part.css_.js +20 -0
- package/src/part.html_.js +20 -8
- package/src/parts/abstract/clip/mathML-subpart.js +4 -0
- package/src/parts/abstract/match/mathML-subpart.js +9 -0
- package/src/parts/abstract/mesh/data-get.js +11 -0
- package/src/parts/abstract/mesh/mathML-subpart.js +10 -0
- package/src/parts/abstract/mesh/ray-cast.js +4 -4
- package/src/parts/abstract/mesh/type.d.ts +10 -0
- package/src/parts/abstract/mix/mathML-subpart.js +9 -0
- package/src/parts/abstract/part/mathML-subpart.js +3 -0
- package/src/parts/abstract/part/mathML.js +22 -0
- package/src/parts/abstract/part/part.json +11 -0
- package/src/parts/abstract/part/type.d.ts +4 -0
- package/src/parts/abstract/part-mask/mathML-subpart.js +1 -0
- package/src/parts/abstract/part-outliner/itemHTML-recursive.js +1 -1
- package/src/parts/abstract/part.json +1 -1
- package/src/parts/abstract/permutation/mathML-subpart.js +10 -0
- package/src/parts/abstract/scroller/mathML-subpart.js +1 -0
- package/src/parts/abstract/scroller/onscroll.js +3 -1
- package/src/parts/abstract/scroller/point-thumb.js +1 -1
- package/src/parts/core/client/async-install.js +1 -1
- package/src/parts/core/part.json +1 -1
- package/src/parts/core/server/sync-install.js +1 -1
- package/src/parts/core/worker/async-take-control.js +1 -1
- package/src/parts/desktop/era/modern/part.css +5 -1
- package/src/parts/desktop/era/vintage/static.css +5 -1
- package/src/parts/desktop/task-bar/menu/menu.html_.js +23 -12
- package/src/parts/desktop/task-bar/part.html_.js +3 -1
- package/src/parts/desktop/task-bar/view-hydrate.js +1 -1
- package/src/parts/desktop/type.d.ts +5 -5
- package/src/parts/desktop/windows/point.js +1 -1
- package/src/parts/desktop/windows/superset-get.js +1 -1
- package/src/{part.css → static.css} +1 -10
- package/src/type.d.ts +172 -10
- package/src/validate.js +3 -3
- package/src/app/kireji/editor/tab-group/equation.html_.js +0 -42
- package/src/parts/abstract/boolean/equation-variable.html +0 -1
- package/src/parts/abstract/box/build.js +0 -24
- package/src/parts/abstract/box/constants.js +0 -1
- package/src/parts/abstract/box/description-abstract +0 -1
- package/src/parts/abstract/box/dimensions_.js +0 -1
- package/src/parts/abstract/box/equation.html_.js +0 -1
- package/src/parts/abstract/box/model_.js +0 -1
- package/src/parts/abstract/box/part.json +0 -3
- package/src/parts/abstract/box/routeID-distribute.js +0 -7
- package/src/parts/abstract/box/routeID-model-to.js +0 -18
- package/src/parts/abstract/box/title-abstract +0 -1
- package/src/parts/abstract/box/type.d.ts +0 -20
- package/src/parts/abstract/match/equation.html_.js +0 -11
- package/src/parts/abstract/mix/equation.html_.js +0 -11
- package/src/parts/abstract/part/equation-variable.html_.js +0 -1
- package/src/parts/abstract/part/equation.html_.js +0 -3
- package/src/parts/abstract/part-mask/equation-variable.html_.js +0 -1
- package/src/parts/abstract/part-mask/equation.html_.js +0 -1
- package/src/parts/abstract/permutation/equation.html_.js +0 -1
- package/src/parts/abstract/scroller/equation-variable.html +0 -1
- package/src/parts/abstract/scroller/equation.html +0 -1
- package/src/parts/user/part.json +0 -3
- package/src/parts/user/title +0 -1
- package/src/parts/user/type.d.ts +0 -2
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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>⋅</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>⋅</mo>").flatMap(term => [term, "<mo>⋅</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">⏟</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"' : ""}
|
|
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
|
|
|
@@ -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>`]
|
|
@@ -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
|
},
|
package/src/parts/core/part.json
CHANGED
|
@@ -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 (
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
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")
|
|
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
|
|
6
|
-
readonly era
|
|
7
|
-
readonly taskBar
|
|
8
|
-
readonly icons
|
|
9
|
-
readonly windows
|
|
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;
|