kireji 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/package.json +1 -1
  2. package/src/app/kireji/editor/point-close.js +1 -1
  3. package/src/app/kireji/editor/point.js +15 -12
  4. package/src/app/kireji/editor/sections/state-space/part.html_.js +5 -1
  5. package/src/app/kireji/editor/static.css +3 -3
  6. package/src/app/kireji/editor/tab-group/build.js +3 -4
  7. package/src/app/kireji/editor/tab-group/equation.html_.js +42 -0
  8. package/src/app/kireji/editor/tab-group/part.css +2 -4
  9. package/src/app/kireji/editor/tab-group/type.d.ts +5 -3
  10. package/src/app/kireji/editor/tab-group/view-add.js +2 -2
  11. package/src/app/kireji/editor/tab-group/view-populate.js +3 -3
  12. package/src/app/kireji/sidebar/static.css +1 -2
  13. package/src/app/kireji/tool-bar/part.css +2 -3
  14. package/src/application-goto.js +11 -0
  15. package/src/build.js +1 -1
  16. package/src/constants.js +1 -0
  17. package/src/part.css +46 -20
  18. package/src/part.html_.js +1 -0
  19. package/src/part.json +3 -0
  20. package/src/parts/abstract/application/early-part.png +0 -0
  21. package/src/parts/abstract/application/part.png +0 -0
  22. package/src/parts/abstract/boolean/equation-variable.html +1 -0
  23. package/src/parts/abstract/box/equation.html_.js +1 -0
  24. package/src/parts/abstract/match/equation.html_.js +11 -0
  25. package/src/parts/abstract/mix/equation.html_.js +11 -0
  26. package/src/parts/abstract/part/equation-variable.html_.js +1 -0
  27. package/src/parts/abstract/part/equation.html_.js +3 -0
  28. package/src/parts/abstract/part-mask/equation-variable.html_.js +1 -0
  29. package/src/parts/abstract/part-mask/equation.html_.js +1 -0
  30. package/src/parts/abstract/part.json +1 -1
  31. package/src/parts/abstract/permutation/build.js +111 -0
  32. package/src/parts/abstract/permutation/constants.js +1 -0
  33. package/src/parts/abstract/permutation/equation.html_.js +1 -0
  34. package/src/parts/abstract/permutation/factor-get-permutation.js +9 -0
  35. package/src/parts/abstract/permutation/model-instance-from.js +1 -0
  36. package/src/parts/abstract/permutation/model-instance-to.js +1 -0
  37. package/src/parts/abstract/permutation/model_.js +3 -0
  38. package/src/parts/abstract/permutation/part.json +46 -0
  39. package/src/parts/abstract/permutation/routeID-collect-instance.js +1 -0
  40. package/src/parts/abstract/permutation/routeID-distribute-instance.js +1 -0
  41. package/src/parts/abstract/permutation/routeID-distribute.js +58 -0
  42. package/src/parts/abstract/permutation/routeID-get-payload.js +8 -0
  43. package/src/parts/abstract/permutation/routeID-get-permutation.js +24 -0
  44. package/src/parts/abstract/permutation/routeID-model-to.js +24 -0
  45. package/src/parts/abstract/permutation/routeID-recompute.js +14 -0
  46. package/src/parts/abstract/permutation/subject-instance-to.js +1 -0
  47. package/src/parts/abstract/permutation/superset-get.js +1 -0
  48. package/src/parts/abstract/permutation/type.d.ts +67 -0
  49. package/src/parts/abstract/permutation/view-add-instance.js +1 -0
  50. package/src/parts/abstract/permutation/view-add.js +4 -0
  51. package/src/parts/abstract/permutation/view-populate.js +36 -0
  52. package/src/parts/abstract/permutation/view-remove-instance.js +1 -0
  53. package/src/parts/abstract/permutation/view-replace-instance.js +1 -0
  54. package/src/parts/abstract/scroller/equation-variable.html +1 -0
  55. package/src/parts/abstract/scroller/equation.html +1 -0
  56. package/src/parts/abstract/tld/part.png +0 -0
  57. package/src/parts/core/client/build.js +12 -2
  58. package/src/parts/core/part.json +1 -1
  59. package/src/parts/core/pointer/handle.js +1 -3
  60. package/src/parts/core/worker/async-take-control.js +2 -2
  61. package/src/parts/desktop/era/modern/part.css +42 -13
  62. package/src/parts/desktop/era/vintage/part.css_.js +1 -1
  63. package/src/parts/desktop/era/vintage/static.css +63 -51
  64. package/src/parts/desktop/part.css_.js +1 -1
  65. package/src/parts/desktop/static.css +7 -0
  66. package/src/parts/desktop/task-bar/build.js +3 -0
  67. package/src/parts/desktop/task-bar/constants.js +3 -1
  68. package/src/parts/desktop/task-bar/menu/button.html_.js +1 -1
  69. package/src/parts/desktop/task-bar/menu/closed/view-remove.js +1 -1
  70. package/src/parts/desktop/task-bar/menu/menu.html_.js +13 -16
  71. package/src/parts/desktop/task-bar/menu/opened/key-next +1 -1
  72. package/src/parts/desktop/task-bar/menu/type.d.ts +2 -5
  73. package/src/parts/desktop/task-bar/menu/view-add.js +1 -1
  74. package/src/parts/desktop/task-bar/part.html_.js +1 -1
  75. package/src/parts/desktop/task-bar/type.d.ts +3 -0
  76. package/src/parts/desktop/task-bar/view-add.js +20 -0
  77. package/src/parts/desktop/type.d.ts +1 -0
  78. package/src/parts/desktop/windows/HTML-render-task.js +1 -0
  79. package/src/parts/desktop/windows/constants.js +2 -0
  80. package/src/parts/desktop/windows/model-instance-from.js +3 -0
  81. package/src/parts/desktop/windows/model-instance-to.js +3 -0
  82. package/src/parts/desktop/windows/model-validate-instance.js +11 -0
  83. package/src/parts/desktop/windows/open-is_.js +1 -0
  84. package/src/parts/desktop/windows/part.json +24 -0
  85. package/src/parts/desktop/windows/point-close.js +13 -0
  86. package/src/parts/desktop/windows/point-hide.js +8 -0
  87. package/src/parts/desktop/windows/point-restore.js +8 -0
  88. package/src/parts/desktop/windows/point.js +12 -0
  89. package/src/parts/desktop/windows/routeID-collect-instance.js +14 -0
  90. package/src/parts/desktop/windows/routeID-distribute-instance.js +17 -0
  91. package/src/parts/desktop/windows/subject-instance-to.js +1 -0
  92. package/src/parts/desktop/windows/superset-get.js +1 -0
  93. package/src/parts/desktop/windows/type.d.ts +32 -0
  94. package/src/parts/desktop/windows/view-add-instance.js +7 -0
  95. package/src/parts/desktop/windows/view-add.js +17 -0
  96. package/src/parts/desktop/windows/view-populate.js +1 -0
  97. package/src/parts/desktop/windows/view-remove-instance.js +1 -0
  98. package/src/parts/desktop/windows/view-replace-instance.js +1 -0
  99. package/src/parts/user/part.json +3 -0
  100. package/src/parts/user/title +1 -0
  101. package/src/parts/user/type.d.ts +2 -0
  102. package/src/point.js +1 -2
  103. package/src/type.d.ts +7 -0
  104. package/src/parts/desktop/menu-appear-on +0 -1
  105. package/src/parts/desktop/task-bar/menu/dismiss/attr-style_.js +0 -1
  106. package/src/parts/desktop/task-bar/menu/dismiss/build.js +0 -3
  107. package/src/parts/desktop/task-bar/menu/dismiss/key-next +0 -1
  108. package/src/parts/desktop/task-bar/menu/dismiss/part.json +0 -3
  109. package/src/parts/desktop/task-bar/menu/dismiss/view-add.js +0 -2
  110. package/src/parts/desktop/task-bar/menu/dismiss/view-remove.js +0 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kireji",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "A web framework for stateful, entropy-perfect, multi-origin web applications. Currently in alpha. Expect breaking changes for version 0. Use with caution!",
5
5
  "files": [
6
6
  "src/",
@@ -1,7 +1,7 @@
1
1
  pointer.handle({
2
2
  click() {
3
3
  const tabIndex = Array.prototype.indexOf.call(Q("#tab-group").children, TARGET_ELEMENT.parentElement)
4
- tabGroup.openTabs.splice(tabIndex, 1)[0]
4
+ tabGroup.openTabs.splice(tabIndex, 1)
5
5
  tabGroup.activeTabIndex = tabGroup.openTabs.length === 0 ? null : (tabGroup.activeTabIndex === tabIndex ? (tabGroup.activeTabIndex < 1 ? 0 : tabGroup.activeTabIndex - 1) : (tabGroup.activeTabIndex > tabIndex ? tabGroup.activeTabIndex - 1 : tabGroup.activeTabIndex))
6
6
  tabGroup.previewTabIndex = tabGroup.openTabs.length === 0 || tabGroup.previewTabIndex === tabIndex ? null : (tabGroup.previewTabIndex > tabIndex ? tabGroup.previewTabIndex - 1 : tabGroup.previewTabIndex)
7
7
  tabGroup.recomputeRouteID(true)
@@ -10,9 +10,7 @@ const pointerConfig = {
10
10
  }
11
11
  },
12
12
  drag(pointerEvent) {
13
- const
14
- { left: tabsLeft, right: tabsRight, top: tabsTop, bottom: tabsBottom } = tabGroup.container.getBoundingClientRect(),
15
- isOverTabGroup = pointerEvent.clientX >= tabsLeft && pointerEvent.clientX <= tabsRight && pointerEvent.clientY >= tabsTop && pointerEvent.clientY <= tabsBottom
13
+ const isOverTabGroup = inRect(pointerEvent, tabGroup.container.getBoundingClientRect())
16
14
  if (isOverTabGroup) {
17
15
  if (tabGroup.container.parentElement.hasAttribute("data-drop-target"))
18
16
  tabGroup.container.parentElement.removeAttribute("data-drop-target")
@@ -39,9 +37,7 @@ const pointerConfig = {
39
37
  }
40
38
  }
41
39
  } else {
42
- const
43
- editorRect = tabGroup.container.parentElement.getBoundingClientRect(),
44
- draggedItemIsOverEditor = pointerEvent.clientX >= editorRect.left && pointerEvent.clientX <= editorRect.right && pointerEvent.clientY >= editorRect.top && pointerEvent.clientY <= editorRect.bottom
40
+ const draggedItemIsOverEditor = inRect(pointerEvent, tabGroup.container.parentElement.getBoundingClientRect())
45
41
  if (draggedItemIsOverEditor && !tabGroup.container.parentElement.hasAttribute("data-drop-target"))
46
42
  tabGroup.container.parentElement.setAttribute("data-drop-target", "")
47
43
  else if (!draggedItemIsOverEditor && tabGroup.container.parentElement.hasAttribute("data-drop-target"))
@@ -67,12 +63,9 @@ const pointerConfig = {
67
63
  drop(pointerEvent) {
68
64
  // TODO: break into separate "click" and "drop" handlers.
69
65
  const
70
- draggedItemRect = TARGET_ELEMENT.getBoundingClientRect(),
71
- draggedItemWasDroppedOntoItself = pointerEvent.clientX >= draggedItemRect.left && pointerEvent.clientX <= draggedItemRect.right && pointerEvent.clientY >= draggedItemRect.top && pointerEvent.clientY <= draggedItemRect.bottom,
72
- tabGroupRect = tabGroup.container.getBoundingClientRect(),
73
- draggedItemWasDroppedOntoTabGroup = pointerEvent.clientX >= tabGroupRect.left && pointerEvent.clientX <= tabGroupRect.right && pointerEvent.clientY >= tabGroupRect.top && pointerEvent.clientY <= tabGroupRect.bottom,
74
- editorRect = tabGroup.container.parentElement.getBoundingClientRect(),
75
- draggedItemWasDroppedOntoEditor = pointerEvent.clientX >= editorRect.left && pointerEvent.clientX <= editorRect.right && pointerEvent.clientY >= editorRect.top && pointerEvent.clientY <= editorRect.bottom,
66
+ draggedItemWasDroppedOntoItself = inRect(pointerEvent, TARGET_ELEMENT.getBoundingClientRect()),
67
+ draggedItemWasDroppedOntoTabGroup = inRect(pointerEvent, tabGroup.container.getBoundingClientRect()),
68
+ draggedItemWasDroppedOntoEditor = inRect(pointerEvent, tabGroup.container.parentElement.getBoundingClientRect()),
76
69
  draggedItemIsAlreadyTheActiveTab = this.activeTabIndexOfDraggedItem !== -1,
77
70
  draggedItemFileData = draggedItemIsAlreadyTheActiveTab ? tabGroup.openTabs[this.activeTabIndexOfDraggedItem] : { part: allParts[PART_INDEX], filename: isNaN(FILE_INDEX) ? undefined : allParts[PART_INDEX].filenames[FILE_INDEX], payload: TAB_PAYLOAD },
78
71
  existingTabIndexOfFileData = draggedItemIsAlreadyTheActiveTab ? this.activeTabIndexOfDraggedItem : tabGroup.openTabs.findIndex(tab => tab.part === draggedItemFileData.part && tab.filename === draggedItemFileData.filename),
@@ -101,6 +94,11 @@ const pointerConfig = {
101
94
  return
102
95
  }
103
96
 
97
+ if (tabGroup.previewTabIndex === null && BigInt(tabGroup.openTabs.length) === tabGroup.maxTabCount) {
98
+ alert("You have too many tabs open!")
99
+ return
100
+ }
101
+
104
102
  let indexOfNewlyCreatedTab = numberOfTabsOpen === 0 ? 0 : tabGroup.activeTabIndex + 1
105
103
  let newPreviewTabIndex = null
106
104
 
@@ -165,6 +163,11 @@ const pointerConfig = {
165
163
  tabGroup.recomputeRouteID(true)
166
164
  } else {
167
165
 
166
+ if (BigInt(tabGroup.openTabs.length) === tabGroup.maxTabCount) {
167
+ alert("You have too many tabs open!")
168
+ return
169
+ }
170
+
168
171
  const previewTab = tabGroup.previewTab
169
172
 
170
173
  // Add the new tab.
@@ -1,12 +1,16 @@
1
1
  const cardinality = activePart.cardinality
2
2
  const cardinalityAsString = instances.includes(activePart) ? cardinality.toLocaleString() : null
3
+
3
4
  return (
4
5
  instances.includes(activePart) ? (
5
6
  "<h3>Cardinality</h3>" +
6
7
  `<p>${cardinalityAsString.length < 16 ? cardinalityAsString : scientific(cardinality, true)}</p>` +
7
8
  `<hr>` +
8
9
  "<h3>Hartley Entropy</h3>" +
9
- `<p>${toCharms(activePart.cardinality)} (${toBits(activePart.cardinality)})</p>`
10
+ `<p>${toCharms(activePart.cardinality)} (${toBits(activePart.cardinality)})</p>` +
11
+ `<hr>` +
12
+ `<h3>Equation</h3>` +
13
+ "<math>" + activePart["equation-variable.html"] + "<mo>=</mo>" + activePart["equation.html"] + "</math>"
10
14
  ) : (
11
15
  "<p class=disabled-message>Abstract parts do not have a concrete state space.</p>"
12
16
  )
@@ -131,7 +131,7 @@ body.light #kireji_app editor-[data-drop-target] :is(editor-view, crumbs-)::afte
131
131
  margin: 0;
132
132
  padding: 0;
133
133
  counter-reset: ln;
134
- padding-bottom: calc(100vh - var(--tab-group-height) - var(--crumbs-height) - var(--task-bar-height) - var(--warning-height) - var(--code-line-height));
134
+ padding-bottom: calc(100vh - var(--tab-group-height) - var(--crumbs-height) - var(--task-bar-height) - var(--warning-height) - var(--code-line-height) - var(--title-bar-height));
135
135
  }
136
136
 
137
137
  #kireji_app editor-view>scroller-:has(#file-viewer) {
@@ -274,7 +274,7 @@ body.modern #kireji_app editor-view>scroller->scroll-content {
274
274
  display: inline-block;
275
275
  }
276
276
 
277
- body.modern #kireji_app #info-state-space>section:not([disabled])>p {
277
+ body.modern #kireji_app #info-state-space>section:not([disabled])>:is(p, math) {
278
278
  float: right;
279
279
  margin: 0;
280
280
  }
@@ -393,7 +393,7 @@ body.vintage #kireji_app crumbs- {
393
393
  }
394
394
 
395
395
  body.vintage #kireji_app #file-viewer {
396
- padding-bottom: calc(100vh - var(--tab-group-height) - var(--crumbs-height) - var(--task-bar-height) - var(--warning-height) - var(--code-line-height) - 24px);
396
+ padding-bottom: calc(100vh - var(--tab-group-height) - var(--crumbs-height) - var(--task-bar-height) - var(--warning-height) - var(--title-bar-height) - var(--code-line-height) - 24px);
397
397
  }
398
398
 
399
399
  body.vintage.light #kireji_app editor-view {
@@ -4,7 +4,7 @@ const tabOffsets = [0n]
4
4
  const permutationSizes = [1n]
5
5
  const payloadSizes = [1n]
6
6
  const subjectCount = BigInt(allSubjects.length)
7
- const maxTabCount = subjectCount
7
+ const maxTabCount = 12n
8
8
  const LSB = []
9
9
  const powerFloor = 2n ** BigInt(subjectCount.toString(2).length - 1)
10
10
  const payloadCardinality = 1n
@@ -52,8 +52,8 @@ tabGroup.define({
52
52
  previewTabIndex: { value: null, writable: true },
53
53
  viewedActiveTab: { value: null, writable: true },
54
54
  viewedPreviewTab: { value: null, writable: true },
55
- viewedPermutation: { value: null, writable: true },
56
- viewedPayload: { value: null, writable: true },
55
+ viewedPermutationRouteID: { value: null, writable: true },
56
+ viewedPayloadRouteID: { value: null, writable: true },
57
57
  viewedOpenTabs: { value: null, writable: true },
58
58
  openTabs: { value: [] },
59
59
  tabOffsets: { value: tabOffsets },
@@ -61,7 +61,6 @@ tabGroup.define({
61
61
  permutationSizes: { value: permutationSizes },
62
62
  payloadSizes: { value: payloadSizes },
63
63
  maxTabCount: { value: maxTabCount },
64
- previousPart: { value: null, writable: true },
65
64
  tree: { value: null, writable: true },
66
65
  container: { value: null, writable: true },
67
66
  FenwickTree: {
@@ -0,0 +1,42 @@
1
+ return `<math>
2
+ <mn>1</mn>
3
+ <mo>+</mo>
4
+ <munderover>
5
+ <mo>&#x2211;</mo>
6
+ <mrow>
7
+ <msub><mi>𝑛</mi><mi>tabs</mi></msub>
8
+ <mo>=</mo>
9
+ <mn>1</mn>
10
+ </mrow>
11
+ <mi>${allSubjects.length}</mi>
12
+ </munderover>
13
+ <mrow>
14
+ <mo>(</mo>
15
+ <msub><mi>𝑛</mi><mi>tabs</mi></msub>
16
+ <mo>+</mo>
17
+ <mn>1</mn>
18
+ <mo>)</mo>
19
+ <msub><mi>𝑛</mi><mi>tabs</mi></msub>
20
+ <mo>&#x00D7;</mo>
21
+ <munderover>
22
+ <mo>&#x220F;</mo>
23
+ <mrow>
24
+ <mi>i</mi>
25
+ <mo>=</mo>
26
+ <mn>1</mn>
27
+ </mrow>
28
+ <mrow>
29
+ <msub><mi>𝑛</mi><mi>tabs</mi></msub>
30
+ </mrow>
31
+ </munderover>
32
+ <mrow>
33
+ <mo>(</mo>
34
+ <mi>${allSubjects.length}</mi>
35
+ <mo>-</mo>
36
+ <mi>i</mi>
37
+ <mo>-</mo>
38
+ <mn>1</mn>
39
+ <mo>)</mo>
40
+ </mrow>
41
+ </mrow>
42
+ </math>`
@@ -145,8 +145,7 @@ body.modern #kireji_app tab-[data-active] .close-tab:hover {
145
145
  body.modern #kireji_app #tab-group {
146
146
  box-shadow:
147
147
  inset 0 -2px 0 -1px var(--bg-un-mode),
148
- inset -2px 0 0 -1px var(--bg-un-mode),
149
- inset 0 2px 0 -1px var(--bg-un-mode);
148
+ inset -2px 0 0 -1px var(--bg-un-mode);
150
149
  }
151
150
 
152
151
  body.modern.dark #kireji_app tab-:not([data-active]):hover {
@@ -164,7 +163,6 @@ body.modern.light #kireji_app tab-:is([data-active], :not([data-active]):hover)
164
163
  body.modern tab- {
165
164
  box-shadow:
166
165
  inset 0 -2px 0 -1px var(--bg-un-mode),
167
- inset 0 2px 0 -1px var(--bg-un-mode),
168
166
  inset -2px 0 0 -1px var(--bg-un-mode);
169
167
  }
170
168
 
@@ -290,7 +288,7 @@ body.vintage>tab-[data-drag-preview] .tab-button {
290
288
  }
291
289
 
292
290
  body.vintage #kireji_app tab-[data-drop-target]::before {
293
- background: var(--pressed-checker), var(--bg-dark-est);
291
+ background: var(--bg-checker), var(--bg-dark-est);
294
292
  width: 4px;
295
293
  }
296
294
 
@@ -41,10 +41,10 @@ declare interface IKirejiAppTabGroup
41
41
  * The most recent preview tab model, as determined while populating the view (not when propagating the route ID). */
42
42
  readonly viewedPreviewTab?: IKirejiAppTabGroupTab
43
43
  /** The most recent permutation route ID, used to quickly determine if the tab arrangement has changed since the last view population. */
44
- readonly viewedPermutation?: bigint
44
+ readonly viewedPermutationRouteID?: bigint
45
45
  /** The most recent payload route ID, used to quickly determine if any payload data has changed since the last view population. */
46
- readonly viewedPayload?: bigint
47
- /** The set of viewed tab objects corresponding to the current `tabGroup.viewedPermutation`. */
46
+ readonly viewedPayloadRouteID?: bigint
47
+ /** The set of viewed tab objects corresponding to the current `tabGroup.viewedPermutationRouteID`. */
48
48
  readonly viewedOpenTabs: IKirejiAppTabGroupTabArray
49
49
  /** A subindex representing which permutation of k open tabs is assigned. */
50
50
  readonly permutationRouteID: bigint
@@ -57,6 +57,8 @@ declare interface IKirejiAppTabGroup
57
57
  readonly activeTabIndex: number
58
58
  /** The index of the preview tab, if one exists. The preview tab is the tab which can be replaced when opening a new tab. */
59
59
  readonly previewTabIndex?: number
60
+ /** The maximum number of tabs that the user can have open, used to mitigate the potentially massive state space of this component. */
61
+ readonly maxTabCount: bigint
60
62
  /** A data type which can be used to performantly rank and unrank permutation indices. */
61
63
  readonly FenwickTree: typeof FenwickTree
62
64
  }
@@ -1,7 +1,7 @@
1
1
  tabGroup.viewedActiveTab = tabGroup.activeTab
2
2
  tabGroup.viewedPreviewTab = tabGroup.previewTab
3
- tabGroup.viewedPermutation = tabGroup.permutationRouteID
4
- tabGroup.viewedPayload = tabGroup.payloadRouteID
3
+ tabGroup.viewedPermutationRouteID = tabGroup.permutationRouteID
4
+ tabGroup.viewedPayloadRouteID = tabGroup.payloadRouteID
5
5
  tabGroup.viewedOpenTabs = [...tabGroup.openTabs]
6
6
  tabGroup.container = Q("#tab-group")
7
7
 
@@ -6,7 +6,7 @@ if (hydrated) {
6
6
 
7
7
  // TODO: Create a "pseudo-part" that has all the same view methods, etc. of a normal part but is dynamically instantiated for dynamic typing.
8
8
 
9
- if (tabGroup.openTabs.length !== tabGroup.viewedOpenTabs.length || tabGroup.viewedPermutation !== tabGroup.permutationRouteID || tabGroup.viewedPayload !== tabGroup.payloadRouteID) {
9
+ if (tabGroup.openTabs.length !== tabGroup.viewedOpenTabs.length || tabGroup.viewedPermutationRouteID !== tabGroup.permutationRouteID || tabGroup.viewedPayloadRouteID !== tabGroup.payloadRouteID) {
10
10
  // TODO: This is a dead-simple approach ... more performant approaches exist.
11
11
  const tabContainer = Q("#tab-group")
12
12
  const existingTabCount = tabGroup.viewedOpenTabs.length
@@ -38,8 +38,8 @@ if (hydrated) {
38
38
 
39
39
  tabContainer.appendChild(newTabElement)
40
40
  }
41
- tabGroup.viewedPermutation = tabGroup.permutationRouteID
42
- tabGroup.viewedPayload = tabGroup.payloadRouteID
41
+ tabGroup.viewedPermutationRouteID = tabGroup.permutationRouteID
42
+ tabGroup.viewedPayloadRouteID = tabGroup.payloadRouteID
43
43
  tabGroup.viewedOpenTabs = [...tabGroup.openTabs]
44
44
  }
45
45
 
@@ -129,8 +129,7 @@
129
129
 
130
130
  body.modern #kireji_app #sidebar-view-header {
131
131
  box-shadow:
132
- inset -2px 0 0 -1px var(--bg-un-mode),
133
- inset 0 2px 0 -1px var(--bg-un-mode);
132
+ inset -2px 0 0 -1px var(--bg-un-mode);
134
133
  }
135
134
 
136
135
  body.modern #kireji_app #sidebar-view {
@@ -22,8 +22,7 @@
22
22
  body.modern #kireji_app tool-bar {
23
23
  box-shadow:
24
24
  inset -2px 0 0 -1px var(--bg-un-mode),
25
- inset 2px 0 0 -1px var(--bg-un-mode),
26
- inset 0 2px 0 -1px var(--bg-un-mode);
25
+ inset 2px 0 0 -1px var(--bg-un-mode);
27
26
  background-color: var(--bg-mode-er);
28
27
  }
29
28
 
@@ -43,7 +42,7 @@ body.vintage #kireji_app tool-bar>button {
43
42
  body.vintage #kireji_app tool-bar>button:active,
44
43
  body.vintage #kireji_app:has(side-bar) tool-bar>button[data-active] {
45
44
  box-shadow: var(--deep-inset);
46
- background: var(--pressed-checker), var(--bg-un-mode);
45
+ background: var(--bg-checker), var(--bg-un-mode);
47
46
  }
48
47
 
49
48
  body.vintage #kireji_app tool-bar>button {
@@ -0,0 +1,11 @@
1
+ const targetLocation = (+_.local ? `http://${HOST}.localhost:${_.port}` : `https://${HOST}`) + encodePathname(_.routeID)
2
+ document.body.classList.add("unhydrated")
3
+
4
+ // Press the button before navigation starts.
5
+ const instanceIndex = desktop.windows.instances.findIndex(window => window.application.host === HOST)
6
+ if (instanceIndex !== -1) {
7
+ const task = document.querySelectorAll(`task-bar>button.task`)[instanceIndex]
8
+ task.classList.add("pressed")
9
+ }
10
+
11
+ location = targetLocation
package/src/build.js CHANGED
@@ -73,7 +73,7 @@ function ƒ(_, compressedSubjectOrigins) {
73
73
  toCharms = (x, unit = true) => encodeSegment(BigInt(x) - 1n).length + (unit ? " charm" + (x !== 1 ? "s" : "") : 0),
74
74
  camelCase = (words, delimiter = "-") => (typeof words === "string" ? words.split(delimiter) : words).map((word, i) => (i ? word[0].toUpperCase() + word.slice(1) : word)).join(""),
75
75
  serialize = value => JSON.stringify(value, (k, v) => (typeof v === "bigint" ? v.toString() + "n" : v), 1),
76
- scientific = (x, html = false) => { x = x.toString(10); const log10 = x.length - 1; x = Math.round((x[0] ?? 0) + (x[1] ?? 0) + (x[2] ?? 0) + (x[3] ?? "0") + "." + (x[4] ?? "0")).toString(); const factor = `${x.slice(0, 1)}.${x.slice(1)}`; return html ? `<math><mn>${factor}</mn><mo>&times;</mo><msup><mn>10</mn><mn>${log10}</mn></msup></math>` : `${factor} × 10` + [...log10.toString()].map(n => '⁰¹²³⁴⁵⁶⁷⁸⁹'[n]).join("") },
76
+ scientific = (x, html = false) => { x = x.toString(10); const log10 = x.length - 1; x = Math.round((x[0] ?? 0) + (x[1] ?? 0) + (x[2] ?? 0) + (x[3] ?? "0") + "." + (x[4] ?? "0")).toString(); const factor = `${x.slice(0, 1)}.${x.slice(1)}`; return html ? `<math><mn>${factor}</mn><mo>&sdot;</mo><msup><mn>10</mn><mn>${log10}</mn></msup></math>` : `${factor} × 10` + [...log10.toString()].map(n => '⁰¹²³⁴⁵⁶⁷⁸⁹'[n]).join("") },
77
77
  btoaUnicode = string => btoa(new TextEncoder("utf-8").encode(string).reduce((data, byte) => data + String.fromCharCode(byte), "")),
78
78
  sanitizeAttr = string => string.replaceAll(/&/g, '&amp;').replaceAll(/"/g, '&quot;').replaceAll(/'/g, '&#39;').replaceAll(/</g, '&lt;').replaceAll(/>/g, '&gt;')
79
79
 
package/src/constants.js CHANGED
@@ -2,6 +2,7 @@ const desktop = _.parts.desktop
2
2
  const taskBar = desktop.taskBar
3
3
  const era = desktop.era
4
4
  const color = desktop.color
5
+ const windows = desktop.windows
5
6
  const core = _.parts.core
6
7
  const worker = core.worker
7
8
  const addressBar = core.addressBar
package/src/part.css CHANGED
@@ -31,7 +31,7 @@ body {
31
31
  --menu-tween: 0;
32
32
  --h: 100vh;
33
33
  --warning-height: 28px;
34
- --wallpaper-height: calc(var(--h) - var(--task-bar-height) - var(--warning-height));
34
+ --wallpaper-height: calc(var(--h) - var(--task-bar-height) - var(--warning-height) - var(--title-bar-height));
35
35
  --wallpaper-width: 100vw;
36
36
  --padding: calc(3.5 * var(--spacing));
37
37
  --gap: calc(2.5 * var(--spacing));
@@ -52,7 +52,7 @@ wallpaper- {
52
52
  --app-height: var(--wallpaper-height);
53
53
  --app-width: var(--wallpaper-width);
54
54
  position: fixed;
55
- top: var(--warning-height);
55
+ top: calc(var(--warning-height) + var(--title-bar-height));
56
56
  height: var(--wallpaper-height);
57
57
  left: 0;
58
58
  right: 0;
@@ -158,19 +158,7 @@ scroll-bar[disabled]>thumb- {
158
158
  display: none;
159
159
  }
160
160
 
161
- task-menu {
162
- position: fixed;
163
- top: 0;
164
- bottom: 0;
165
- left: 0;
166
- right: 0;
167
- margin: 0;
168
- padding: 0;
169
- outline: none;
170
- }
171
-
172
- button,
173
- menu-button {
161
+ button {
174
162
  background: transparent;
175
163
  padding: 0;
176
164
  margin: 0;
@@ -184,13 +172,13 @@ button:focus {
184
172
  outline: none;
185
173
  }
186
174
 
187
- task-bar>menu-button {
188
- position: absolute;
189
- left: var(--spacing);
190
- bottom: var(--spacing);
175
+ task-bar>button {
176
+ position: relative;
177
+ margin-left: var(--spacing);
178
+ margin-bottom: var(--spacing);
191
179
  }
192
180
 
193
- task-sidebar {
181
+ task-menu {
194
182
  margin: 0;
195
183
  position: fixed;
196
184
  overflow: hidden;
@@ -321,4 +309,42 @@ body.dark warning- {
321
309
  #stats-tray-item,
322
310
  #clock-tray-item {
323
311
  font-size: revert;
312
+ }
313
+
314
+ title-bar {
315
+ display: flex;
316
+ flex-flow: row nowrap;
317
+ margin: 0;
318
+ padding: 0;
319
+ height: var(--title-bar-height);
320
+ line-height: var(--title-bar-height);
321
+ position: fixed;
322
+ top: var(--warning-height);
323
+ left: 0;
324
+ right: 0;
325
+ }
326
+
327
+ title-bar>button {
328
+ width: var(--icon-size);
329
+ }
330
+
331
+ title-bar>.hide:before {
332
+ content: "_"
333
+ }
334
+
335
+ title-bar>.restore:before {
336
+ content: "☐"
337
+ }
338
+
339
+ /* Temp */
340
+ title-bar>.restore {
341
+ display: none;
342
+ }
343
+
344
+ title-bar>.maximize:before {
345
+ content: "⛶"
346
+ }
347
+
348
+ title-bar>.close:before {
349
+ content: "✕"
324
350
  }
package/src/part.html_.js CHANGED
@@ -34,6 +34,7 @@ const bodyHTML =
34
34
  `🚧 App in Alpha. Features subject to change/break without notice.`
35
35
  ) +
36
36
  `</warning->` +
37
+ `<title-bar><img class="part-icon" src="${_.application.placeholderImage("part.png")}"/>${application.title}<flex-spacer></flex-spacer><button class=hide ${windows.pointAttr("hidePoint")}></button><button class=restore ${windows.pointAttr("restorePoint")} disabled></button><button class=close ${windows.pointAttr("closePoint")}></button></title-bar>` +
37
38
  `<wallpaper- class=app-container id=${application.host.replaceAll(".", "_")} tabIndex=0${application.attributes ? ` ${application.attributes}` : ""}${application.style ? ` style="${application.style}"` : ""}>` + (
38
39
  application["part.html"]
39
40
  ) +
package/src/part.json CHANGED
@@ -16,5 +16,8 @@
16
16
  "early-get-images": [
17
17
  "BODY_HTML",
18
18
  "HEAD_HTML"
19
+ ],
20
+ "application-goto": [
21
+ "HOST"
19
22
  ]
20
23
  }
@@ -0,0 +1 @@
1
+ <math><mi>𝑏</mi></math>
@@ -0,0 +1 @@
1
+ return `<math>${box.dimensions.map(dimension => `<mn>${dimension}</mn>`).join("<mo>&sdot;</mo>")}</math>`
@@ -0,0 +1,11 @@
1
+ return "<math>" + (
2
+ match.length ? (
3
+ match.length > 4 ? (
4
+ `<mo>∑</mo><msub><mi>𝑘</mi><mi>𝑝</mi></msub><mtext>,</mtext><mspace width="0.5em"/><mi>𝑝</mi><mo>∈</mo><mi>subparts</mi><mo>(</mo><msub><mi>P</mi><mi>${part.key ?? "ecosystem"}</mi></msub><mo>)</mo>`
5
+ ) : (
6
+ match.map(factor => factor["equation-variable.html"]).join("<mo>+</mo>")
7
+ )
8
+ ) : (
9
+ "<mn>1</mn>"
10
+ )
11
+ ) + "</math>"
@@ -0,0 +1,11 @@
1
+ return "<math>" + (
2
+ mix.length ? (
3
+ mix.length > 4 ? (
4
+ `<mo>∏</mo><msub><mi>𝑘</mi><mi>𝑝</mi></msub><mtext>,</mtext><mspace width="0.5em"/><mi>𝑝</mi><mo>∈</mo><mi>subparts</mi><mo>(</mo><msub><mi>P</mi><mi>${part.key ?? "ecosystem"}</mi></msub><mo>)</mo>`
5
+ ) : (
6
+ mix.map(factor => factor["equation-variable.html"]).join("<mo>&sdot;</mo>")
7
+ )
8
+ ) : (
9
+ "<mn>1</mn>"
10
+ )
11
+ ) + "</math>"
@@ -0,0 +1 @@
1
+ return `<math><msub><mi>𝑘</mi><mi>${part.key ?? "ecosystem"}</mi></msub></math>`
@@ -0,0 +1,3 @@
1
+ const cardinality = part.cardinality
2
+ const cardinalityAsString = instances.includes(part) ? cardinality.toString() : null
3
+ return cardinalityAsString.length < 16 ? `<math><mn>${cardinalityAsString}</mn></math>` : scientific(cardinality, true)
@@ -0,0 +1 @@
1
+ return `<math><msup><mn>2</mn><mn>${partMask.superset.length}</mn></msup></math>`
@@ -0,0 +1 @@
1
+ return `<math>${partMask["equation-variable.html"]}</math>`
@@ -1,3 +1,3 @@
1
1
  {
2
- "extends": "mix"
2
+ "extends": "coming-soon"
3
3
  }
@@ -0,0 +1,111 @@
1
+
2
+ /* TODO:
3
+ * 1. Instantiate a concrete innstance of an abstract part per-instance. Offload all per-instance logic there.
4
+ * - Such a part will have optional subparts 'instance' and 'meta'
5
+ * - "instance" corresponds to each instance part's statically-sized data model
6
+ * - which also receives its specific subject assigment from the outside (not part of it's route ID)
7
+ * - "meta" (name pending) corresponds to a non-instance-specific part whose cardinality is dependant upon the number of instances.
8
+ * - get its implementation details by generalizing the active and preview tab data in the tab group.
9
+ * - At build time, the parent permutation will need to be able to query this part to get its cardinality once for every instance up to the max count.
10
+ * - This part can support mixes, matches, etc. and might even be the ideal place to place a sub-permutation.
11
+ * 2. Convert the tab group to use this abstract type.
12
+ * Considerations;
13
+ * - How do we inspect the states of existing tab instances in `kireji.app`?
14
+ * - Files will be easy: they are part of the abstract.
15
+ * - Perhaps the state space box depicts an array of instance space states instead of the single state? Perhaps that is all that is needed?
16
+ * - Then, how do we depict the states of subparts of the parent part? Do we simply have an array for the entire instance part's tree?
17
+ * - We might need "push", "pop", "insert", "splice" and/or similar array methods to make it easier to modify the instance set on the fly. */
18
+
19
+ // Memoize the permutation data.
20
+ const instanceOffsets = [0n]
21
+ const instanceBitDepths = [0n, 0n]
22
+ const permutationSizes = [1n]
23
+ const payloadCardinality = 2000n ** 4n
24
+ const payloadSizes = [1n]
25
+ const superset = permutation.getSuperset()
26
+ const supersetSize = BigInt(superset.length)
27
+ const maxInstanceCount = supersetSize
28
+ const LSB = []
29
+ const powerFloor = 2n ** BigInt(supersetSize.toString(2).length - 1)
30
+
31
+ let cardinality = 1n
32
+
33
+ for (let subsetSize = 1n, permutationSize = 1n, payloadSize = 1n; subsetSize <= supersetSize; subsetSize++) {
34
+
35
+ // Memoize a prototype LSB array to simplify initialization of Fenwick tree instances.
36
+ LSB[subsetSize - 1n] = subsetSize & -subsetSize
37
+
38
+ if (subsetSize > maxInstanceCount)
39
+ continue
40
+
41
+ // Increase the permutation size based on subset size.
42
+ permutationSize *= supersetSize - subsetSize + 1n
43
+
44
+ // Increase the payload size.
45
+ payloadSize *= payloadCardinality
46
+ permutationSizes[subsetSize] = permutationSize
47
+ payloadSizes[subsetSize] = payloadSize
48
+ instanceOffsets[subsetSize] = cardinality
49
+
50
+ cardinality +=
51
+ permutationSize
52
+ * payloadSize
53
+
54
+ // Enable O(1) recovery of subsetSize later.
55
+ const bitDepth = cardinality.toString(2).length
56
+ while (bitDepth > instanceBitDepths.length)
57
+ instanceBitDepths.push(subsetSize - 1n)
58
+ instanceBitDepths[bitDepth] = subsetSize
59
+ }
60
+
61
+ permutation.define({
62
+ instanceOffsets: { value: instanceOffsets },
63
+ instanceBitDepths: { value: instanceBitDepths },
64
+ permutationSizes: { value: permutationSizes },
65
+ payloadCardinality: { value: payloadCardinality },
66
+ payloadSizes: { value: payloadSizes },
67
+ superset: { value: superset },
68
+ supersetSize: { value: supersetSize },
69
+ maxInstanceCount: { value: maxInstanceCount },
70
+
71
+ cardinality: { value: cardinality },
72
+
73
+ permutationRouteID: { value: null, writable: true },
74
+ viewedPermutationRouteID: { value: null, writable: true },
75
+
76
+ payloadRouteID: { value: null, writable: true },
77
+ viewedPayloadRouteID: { value: null, writable: true },
78
+
79
+ instances: { value: [] },
80
+ viewedInstances: { value: null, writable: true },
81
+
82
+ tree: { value: null, writable: true },
83
+ FenwickTree: {
84
+ value: class FenwickTree {
85
+ constructor() {
86
+ this.tree = [...LSB]
87
+ }
88
+ update(i, val) {
89
+ for (; i < supersetSize; i += LSB[i])
90
+ this.tree[i] += val
91
+ }
92
+ query(i) {
93
+ let sum = 0n
94
+ for (; i >= 0n; i -= LSB[i])
95
+ sum += this.tree[i]
96
+ return sum
97
+ }
98
+ findNthAvailable(n) {
99
+ let nthAvailable = 0n
100
+ for (let p = powerFloor; p > 0n; p /= 2n) {
101
+ const i = nthAvailable + p
102
+ if (i <= supersetSize && this.tree[i - 1n] <= n) {
103
+ n -= this.tree[i - 1n]
104
+ nthAvailable = i
105
+ }
106
+ }
107
+ return nthAvailable
108
+ }
109
+ }
110
+ }
111
+ })
@@ -0,0 +1 @@
1
+ const permutation = this
@@ -0,0 +1 @@
1
+ return `<math><mtext>TBD for ${permutation.maxInstanceCount} max instances.</mtext></math>`
@@ -0,0 +1,9 @@
1
+ const indexOfLastPossibleInstanceSubject = permutation.supersetSize - 1n
2
+ const indexOfLastInstance = INSTANCE_COUNT - 1n
3
+
4
+ let permutationFactorOfCurrentInstanceIndex = 1n
5
+
6
+ for (let consumedInstanceIndices = 0n; consumedInstanceIndices < indexOfLastInstance - CURRENT_INSTANCE_INDEX; consumedInstanceIndices++)
7
+ permutationFactorOfCurrentInstanceIndex *= indexOfLastPossibleInstanceSubject - CURRENT_INSTANCE_INDEX - consumedInstanceIndices
8
+
9
+ return permutationFactorOfCurrentInstanceIndex