poetry-core 0.0.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 (166) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/DESIGN.md +145 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +30 -0
  6. data/THIRD_PARTY_NOTICES.md +507 -0
  7. data/app/components/poetry/core/box/component.rb +82 -0
  8. data/app/components/poetry/core/component.rb +390 -0
  9. data/app/components/poetry/core/concerns/agent_tools.rb +418 -0
  10. data/app/components/poetry/core/concerns/declared_attributes.rb +267 -0
  11. data/app/components/poetry/core/concerns/introspection.rb +533 -0
  12. data/app/components/poetry/core/concerns/options.rb +262 -0
  13. data/app/components/poetry/core/concerns/parts.rb +148 -0
  14. data/app/components/poetry/core/concerns/stimulus.rb +363 -0
  15. data/app/components/poetry/core/concerns/styles.rb +323 -0
  16. data/app/components/poetry/core/style.rb +150 -0
  17. data/app/components/poetry/core/wrapper/component.rb +90 -0
  18. data/app/javascript/poetry/core/accordion_controller.js +165 -0
  19. data/app/javascript/poetry/core/action_bar_controller.js +109 -0
  20. data/app/javascript/poetry/core/autocomplete_controller.js +220 -0
  21. data/app/javascript/poetry/core/calendar_controller.js +406 -0
  22. data/app/javascript/poetry/core/carousel_controller.js +167 -0
  23. data/app/javascript/poetry/core/checkbox_group_controller.js +97 -0
  24. data/app/javascript/poetry/core/checked_controller.js +208 -0
  25. data/app/javascript/poetry/core/clipboard_text_controller.js +111 -0
  26. data/app/javascript/poetry/core/combobox_controller.js +1095 -0
  27. data/app/javascript/poetry/core/command_controller.js +510 -0
  28. data/app/javascript/poetry/core/context_menu_controller.js +204 -0
  29. data/app/javascript/poetry/core/date_field_controller.js +584 -0
  30. data/app/javascript/poetry/core/date_picker_controller.js +111 -0
  31. data/app/javascript/poetry/core/deferred_controller.js +111 -0
  32. data/app/javascript/poetry/core/dialog_controller.js +206 -0
  33. data/app/javascript/poetry/core/dismissable_controller.js +182 -0
  34. data/app/javascript/poetry/core/drawer_controller.js +365 -0
  35. data/app/javascript/poetry/core/file_input_controller.js +191 -0
  36. data/app/javascript/poetry/core/focus_scope_controller.js +162 -0
  37. data/app/javascript/poetry/core/helpers/announce.js +228 -0
  38. data/app/javascript/poetry/core/helpers/breakpoint.js +28 -0
  39. data/app/javascript/poetry/core/helpers/collection.js +18 -0
  40. data/app/javascript/poetry/core/helpers/direction.js +15 -0
  41. data/app/javascript/poetry/core/helpers/escape.js +38 -0
  42. data/app/javascript/poetry/core/helpers/filter_rank.js +104 -0
  43. data/app/javascript/poetry/core/helpers/focus_guards.js +46 -0
  44. data/app/javascript/poetry/core/helpers/hotkey.js +43 -0
  45. data/app/javascript/poetry/core/helpers/id_integrity.js +65 -0
  46. data/app/javascript/poetry/core/helpers/incomplete_date.js +328 -0
  47. data/app/javascript/poetry/core/helpers/mask.js +283 -0
  48. data/app/javascript/poetry/core/helpers/portal.js +217 -0
  49. data/app/javascript/poetry/core/helpers/presence.js +210 -0
  50. data/app/javascript/poetry/core/helpers/registration_guard.js +76 -0
  51. data/app/javascript/poetry/core/helpers/scroll_lock.js +67 -0
  52. data/app/javascript/poetry/core/helpers/scroller_geometry.js +422 -0
  53. data/app/javascript/poetry/core/helpers/state.js +80 -0
  54. data/app/javascript/poetry/core/helpers/tabbable.js +56 -0
  55. data/app/javascript/poetry/core/helpers/turbo_cache.js +21 -0
  56. data/app/javascript/poetry/core/helpers/typeahead.js +85 -0
  57. data/app/javascript/poetry/core/hotkey_controller.js +55 -0
  58. data/app/javascript/poetry/core/hover_card_controller.js +431 -0
  59. data/app/javascript/poetry/core/index.js +218 -0
  60. data/app/javascript/poetry/core/mask_controller.js +500 -0
  61. data/app/javascript/poetry/core/menu_controller.js +1050 -0
  62. data/app/javascript/poetry/core/menubar_controller.js +329 -0
  63. data/app/javascript/poetry/core/message_scroller_controller.js +930 -0
  64. data/app/javascript/poetry/core/navigation_menu_controller.js +458 -0
  65. data/app/javascript/poetry/core/number_field_controller.js +404 -0
  66. data/app/javascript/poetry/core/optimistic_form_controller.js +56 -0
  67. data/app/javascript/poetry/core/otp_controller.js +219 -0
  68. data/app/javascript/poetry/core/popover_controller.js +300 -0
  69. data/app/javascript/poetry/core/popper_controller.js +439 -0
  70. data/app/javascript/poetry/core/pressed_controller.js +74 -0
  71. data/app/javascript/poetry/core/questionnaire_controller.js +468 -0
  72. data/app/javascript/poetry/core/radio_group_controller.js +197 -0
  73. data/app/javascript/poetry/core/resizable_controller.js +202 -0
  74. data/app/javascript/poetry/core/roving_focus_controller.js +215 -0
  75. data/app/javascript/poetry/core/scroll_spy_controller.js +84 -0
  76. data/app/javascript/poetry/core/search_field_controller.js +95 -0
  77. data/app/javascript/poetry/core/select_controller.js +924 -0
  78. data/app/javascript/poetry/core/sensitive_input_controller.js +195 -0
  79. data/app/javascript/poetry/core/sheet_controller.js +24 -0
  80. data/app/javascript/poetry/core/sidebar_controller.js +272 -0
  81. data/app/javascript/poetry/core/slider_controller.js +419 -0
  82. data/app/javascript/poetry/core/state_controller.js +82 -0
  83. data/app/javascript/poetry/core/table_selection_controller.js +153 -0
  84. data/app/javascript/poetry/core/tabs_controller.js +151 -0
  85. data/app/javascript/poetry/core/tag_group_controller.js +134 -0
  86. data/app/javascript/poetry/core/toast_controller.js +228 -0
  87. data/app/javascript/poetry/core/toast_trigger_controller.js +26 -0
  88. data/app/javascript/poetry/core/toaster_controller.js +197 -0
  89. data/app/javascript/poetry/core/toggle_group_controller.js +206 -0
  90. data/app/javascript/poetry/core/tooltip_controller.js +541 -0
  91. data/app/javascript/poetry/core/tree_controller.js +265 -0
  92. data/app/javascript/poetry/core/vendor/floating_ui_core.js +1043 -0
  93. data/app/javascript/poetry/core/vendor/floating_ui_dom.js +794 -0
  94. data/app/javascript/poetry/core/vendor/floating_ui_utils.js +141 -0
  95. data/app/javascript/poetry/core/vendor/floating_ui_utils_dom.js +170 -0
  96. data/app/views/poetry/core/preview.html.erb +13 -0
  97. data/config/component_registry.yml +20 -0
  98. data/config/controllers_manifest.json +1528 -0
  99. data/config/importmap.rb +11 -0
  100. data/config/state_vocabulary.json +31 -0
  101. data/lib/active_model/type/list.rb +33 -0
  102. data/lib/active_model/type/symbol.rb +36 -0
  103. data/lib/poetry/core/check/stable_identity.rb +104 -0
  104. data/lib/poetry/core/check.rb +1445 -0
  105. data/lib/poetry/core/config.rb +286 -0
  106. data/lib/poetry/core/contrib/wrapped_helper.rb +68 -0
  107. data/lib/poetry/core/css/bem_merger.rb +45 -0
  108. data/lib/poetry/core/css/bem_reference.rb +87 -0
  109. data/lib/poetry/core/css/override_scan.rb +110 -0
  110. data/lib/poetry/core/css/resolver.rb +161 -0
  111. data/lib/poetry/core/css/safelist.rb +41 -0
  112. data/lib/poetry/core/css/tailwind_merger.rb +102 -0
  113. data/lib/poetry/core/css/template_classes.rb +102 -0
  114. data/lib/poetry/core/css/theme_coverage.rb +72 -0
  115. data/lib/poetry/core/css/var_coverage.rb +75 -0
  116. data/lib/poetry/core/css/verifier.rb +106 -0
  117. data/lib/poetry/core/design_lint.rb +720 -0
  118. data/lib/poetry/core/design_md/import.rb +250 -0
  119. data/lib/poetry/core/design_md.rb +461 -0
  120. data/lib/poetry/core/engine.rb +71 -0
  121. data/lib/poetry/core/errors.rb +53 -0
  122. data/lib/poetry/core/html/attributes.rb +667 -0
  123. data/lib/poetry/core/icons.rb +157 -0
  124. data/lib/poetry/core/llms_text.rb +354 -0
  125. data/lib/poetry/core/page_architectures.rb +304 -0
  126. data/lib/poetry/core/part_contract.rb +285 -0
  127. data/lib/poetry/core/preview/abstract.rb +121 -0
  128. data/lib/poetry/core/preview/base.rb +227 -0
  129. data/lib/poetry/core/preview/sidecarable.rb +136 -0
  130. data/lib/poetry/core/preview/template.rb +186 -0
  131. data/lib/poetry/core/recipe_items.rb +82 -0
  132. data/lib/poetry/core/registry.rb +363 -0
  133. data/lib/poetry/core/registry_address.rb +115 -0
  134. data/lib/poetry/core/registry_client.rb +217 -0
  135. data/lib/poetry/core/registry_installer.rb +234 -0
  136. data/lib/poetry/core/registry_items.rb +184 -0
  137. data/lib/poetry/core/skill_text.rb +288 -0
  138. data/lib/poetry/core/stable_id.rb +110 -0
  139. data/lib/poetry/core/stimulus/builder.rb +395 -0
  140. data/lib/poetry/core/stimulus/declarations.rb +444 -0
  141. data/lib/poetry/core/stimulus/manifest.rb +68 -0
  142. data/lib/poetry/core/stimulus/merger.rb +131 -0
  143. data/lib/poetry/core/stimulus_contract.rb +263 -0
  144. data/lib/poetry/core/tag_helper.rb +10 -0
  145. data/lib/poetry/core/template_compile.rb +74 -0
  146. data/lib/poetry/core/token_import.rb +317 -0
  147. data/lib/poetry/core/tokens/color.rb +215 -0
  148. data/lib/poetry/core/tokens/contrast_gate.rb +120 -0
  149. data/lib/poetry/core/tokens/generator.rb +211 -0
  150. data/lib/poetry/core/tokens.rb +117 -0
  151. data/lib/poetry/core/version.rb +9 -0
  152. data/lib/poetry/core.rb +52 -0
  153. data/lib/poetry-core.rb +5 -0
  154. data/tokens/aliases.css +145 -0
  155. data/tokens/tailwind-theme.css +47 -0
  156. data/tokens/tokens.css +78 -0
  157. data/tokens/tokens.dtcg.json +779 -0
  158. data/vendor/floating-ui/LICENSE +20 -0
  159. data/vendor/floating-ui/VENDORED_VERSIONS +15 -0
  160. data/vendor/shadcn-tailwind/LICENSE +21 -0
  161. data/vendor/shadcn-tailwind/VENDORED_COMMIT +1 -0
  162. data/vendor/shadcn-tailwind/tailwind.css +629 -0
  163. data/vendor/tw-animate-css/LICENSE +21 -0
  164. data/vendor/tw-animate-css/VENDORED_VERSION +1 -0
  165. data/vendor/tw-animate-css/tw-animate.css +1 -0
  166. metadata +267 -0
@@ -0,0 +1,204 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // The ContextMenu DELTA layer: trigger
4
+ // acquisition + pointer-point capture ONLY. Everything menu-shaped (open
5
+ // state machine, items, typeahead, submenus, dismissal, the layer stack)
6
+ // stays with poetry--core--menu on the same root; positioning stays with
7
+ // poetry--core--popper, driven here through its VIRTUAL-ANCHOR attribute
8
+ // (data-poetry--core--popper-anchor-point-value="x,y" - the DOM is the
9
+ // store, so the write works whether or not popper has connected yet).
10
+ //
11
+ // Input paths (all contractual):
12
+ // - contextmenu (mouse right-click, or Shift+F10 / the ContextMenu key on a
13
+ // focused surface): preventDefault, capture the point, open. A
14
+ // keyboard-synthesized event carries no usable point (0,0) - the anchor
15
+ // attribute is CLEARED so popper falls back to the trigger surface rect
16
+ // (deliberately better than a 0,0 fallback).
17
+ // - long-press (touch/pen ONLY - mouse never long-presses): pointerdown
18
+ // starts a longPressDelay timer (700ms default, exposed as a
19
+ // Value); ANY pointermove/pointerup/pointercancel cancels (no slop radius
20
+ // - the platform's own touch slop absorbs jitter); a second pointerdown
21
+ // restarts (multi-touch guard); the contextmenu handler itself clears the
22
+ // timer (Android synthesizes contextmenu from long-press - clearing there
23
+ // prevents double-open). data-pressing on the surface is the styleable
24
+ // long-press feedback window (poetry addition).
25
+ // - disabled STANDS THE HANDLERS DOWN (no preventDefault): the
26
+ // browser-native context menu returns - never a dead right-click.
27
+ const TRIGGER_SELECTOR = '[data-slot$="menu-trigger"]'
28
+ const MENU = "poetry--core--menu"
29
+ const ANCHOR_POINT_ATTRIBUTE = "data-poetry--core--popper-anchor-point-value"
30
+ const EVENT_PREFIX = "poetry:context-menu"
31
+
32
+ export default class ContextMenuController extends Controller {
33
+ // The events this controller dispatches (manifest surface;
34
+ // events_declaration.test.js enforces the list stays honest).
35
+ static events = ["poetry:context-menu:open"]
36
+
37
+ static values = {
38
+ longPressDelay: { type: Number, default: 700 },
39
+ disabled: { type: Boolean, default: false }
40
+ }
41
+
42
+ #timer = null
43
+ #suppressNative = null
44
+ #onMenuClosed = null
45
+
46
+ /** Clears any armed long-press and stops the native-menu suppression. */
47
+ disconnect() {
48
+ this.#clearLongPress()
49
+ this.#stopSuppressingNative()
50
+ }
51
+
52
+ /**
53
+ * Stimulus value callback: disabling mid-press clears the armed
54
+ * long-press.
55
+ *
56
+ * @param {boolean} disabled
57
+ */
58
+ disabledValueChanged(disabled) {
59
+ if (disabled) this.#clearLongPress()
60
+ }
61
+
62
+ /**
63
+ * The trigger surface's contextmenu action. Re-invoking on an
64
+ * already-open menu re-captures the point and repositions (popper's
65
+ * anchorPoint value is reactive; autoUpdate re-reads the stored point).
66
+ *
67
+ * @param {MouseEvent} event
68
+ */
69
+ open(event) {
70
+ if (this.disabledValue) return // native menu passthrough - do NOT preventDefault
71
+
72
+ event.preventDefault()
73
+ this.#clearLongPress()
74
+
75
+ const point = this.#pointOf(event)
76
+
77
+ this.#openAt(point, point ? "pointer" : "keyboard")
78
+ }
79
+
80
+ /**
81
+ * The surface's pointerdown action - touch/pen long-press. While open,
82
+ * a press on the surface closes first (press-again-to-dismiss), then
83
+ * the timer arms for a fresh open.
84
+ *
85
+ * @param {PointerEvent} event
86
+ */
87
+ pressStart(event) {
88
+ if (this.disabledValue || event.pointerType === "mouse") return
89
+
90
+ this.#clearLongPress()
91
+
92
+ if (this.#isOpen()) this.#menu()?.close("outside-press")
93
+
94
+ const point = { x: event.clientX, y: event.clientY }
95
+
96
+ this.#trigger()?.setAttribute("data-pressing", "")
97
+ this.#timer = window.setTimeout(() => {
98
+ this.#timer = null
99
+ this.#clearPressing()
100
+ this.#openAt(point, "long-press")
101
+ }, this.longPressDelayValue)
102
+ }
103
+
104
+ /**
105
+ * pointermove / pointerup / pointercancel - any of them cancels the
106
+ * armed press.
107
+ */
108
+ pressCancel() {
109
+ this.#clearLongPress()
110
+ }
111
+
112
+ // --- the anchor contract ---
113
+
114
+ #openAt(point, input) {
115
+ // The attribute is canonical (inspectable, server-settable, testable);
116
+ // an empty value returns popper to element anchoring - the trigger
117
+ // surface rect (the positionless-open / keyboard fallback).
118
+ this.element.setAttribute(ANCHOR_POINT_ATTRIBUTE, point ? `${point.x},${point.y}` : "")
119
+
120
+ if (input === "keyboard") this.#menu()?.open("list-navigation", { seed: "first" })
121
+ else this.#menu()?.open("trigger-press")
122
+ this.#suppressNativeWhileOpen()
123
+ this.dispatch("open", {
124
+ prefix: EVENT_PREFIX,
125
+ detail: { x: point?.x ?? null, y: point?.y ?? null, input }
126
+ })
127
+ }
128
+
129
+ // --- native-menu suppression while open ---
130
+
131
+ // While open, a document-level contextmenu listener suppresses the
132
+ // native menu everywhere - poetry renders no viewport-covering backdrop
133
+ // element, so the document listener IS the backdrop; it deliberately
134
+ // covers the popup itself too (without it, right-clicking an
135
+ // item of the OPEN menu still spawns the native menu over it). Second
136
+ // right-clicks on the surface stay live - the trigger's own handler runs
137
+ // first and re-captures the point.
138
+ #suppressNativeWhileOpen() {
139
+ if (this.#suppressNative) return
140
+
141
+ this.#suppressNative = (event) => {
142
+ if (this.#isOpen()) event.preventDefault()
143
+ }
144
+ this.#onMenuClosed = () => {
145
+ // A reopen during the previous close's exit presence keeps the
146
+ // suppressor - the eventual real close dispatches closed again.
147
+ if (!this.#isOpen()) this.#stopSuppressingNative()
148
+ }
149
+ document.addEventListener("contextmenu", this.#suppressNative)
150
+ this.element.addEventListener("poetry:menu:closed", this.#onMenuClosed)
151
+ }
152
+
153
+ #stopSuppressingNative() {
154
+ if (!this.#suppressNative) return
155
+
156
+ document.removeEventListener("contextmenu", this.#suppressNative)
157
+ this.element.removeEventListener("poetry:menu:closed", this.#onMenuClosed)
158
+ this.#suppressNative = null
159
+ this.#onMenuClosed = null
160
+ }
161
+
162
+ // A keyboard-synthesized contextmenu carries unreliable coordinates
163
+ // (0,0 per browser) - treat the origin as "no usable point".
164
+ #pointOf(event) {
165
+ const x = event.clientX
166
+ const y = event.clientY
167
+
168
+ if (!Number.isFinite(x) || !Number.isFinite(y)) return null
169
+ if (x === 0 && y === 0) return null
170
+
171
+ return { x, y }
172
+ }
173
+
174
+ // --- long-press bookkeeping ---
175
+
176
+ #clearLongPress() {
177
+ if (this.#timer !== null) {
178
+ window.clearTimeout(this.#timer)
179
+ this.#timer = null
180
+ }
181
+
182
+ this.#clearPressing()
183
+ }
184
+
185
+ #clearPressing() {
186
+ this.#trigger()?.removeAttribute("data-pressing")
187
+ }
188
+
189
+ // --- structural resolution (shared-root composition, no outlets) ---
190
+
191
+ #menu() {
192
+ return this.application.getControllerForElementAndIdentifier(this.element, MENU)
193
+ }
194
+
195
+ #trigger() {
196
+ return this.element.querySelector(TRIGGER_SELECTOR)
197
+ }
198
+
199
+ #isOpen() {
200
+ const trigger = this.#trigger()
201
+
202
+ return Boolean(trigger) && trigger.hasAttribute("data-popup-open")
203
+ }
204
+ }