@maccesar/titools 4.4.0 → 4.4.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 (39) hide show
  1. package/README.md +9 -12
  2. package/package.json +1 -1
  3. package/skills/purgetss/SKILL.md +4 -9
  4. package/skills/ti-api/references/api-core.md +24 -69
  5. package/skills/ti-api/references/api-data-network.md +18 -63
  6. package/skills/ti-api/references/api-media.md +15 -49
  7. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +6 -20
  8. package/skills/ti-api/references/api-modules-map.md +17 -40
  9. package/skills/ti-api/references/api-modules-nfc.md +23 -56
  10. package/skills/ti-api/references/api-ui-android.md +16 -37
  11. package/skills/ti-api/references/api-ui-extras.md +28 -72
  12. package/skills/ti-api/references/api-ui-lists.md +14 -35
  13. package/skills/ti-api/references/api-ui-text-input.md +13 -39
  14. package/skills/ti-api/references/api-ui-windows-navigation.md +17 -43
  15. package/skills/ti-api/references/api-xml-global.md +25 -60
  16. package/skills/ti-expert/SKILL.md +8 -11
  17. package/skills/ti-expert/references/adaptive-layouts.md +15 -43
  18. package/skills/ti-expert/references/alloy-builtins.md +1 -4
  19. package/skills/ti-expert/references/alloy-structure.md +4 -12
  20. package/skills/ti-expert/references/anti-patterns.md +16 -45
  21. package/skills/ti-expert/references/code-conventions.md +2 -6
  22. package/skills/ti-expert/references/controller-patterns.md +1 -3
  23. package/skills/ti-expert/references/examples.md +3 -10
  24. package/skills/ti-expert/references/feedback-migration.md +17 -39
  25. package/skills/ti-expert/references/feedback-surfaces.md +19 -48
  26. package/skills/ti-expert/references/feedback-widget-contracts.md +31 -69
  27. package/skills/ti-expert/references/file-type-association.md +265 -0
  28. package/skills/ti-expert/references/migration-patterns.md +8 -18
  29. package/skills/ti-expert/references/sharing.md +227 -0
  30. package/skills/ti-expert/references/theming.md +20 -45
  31. package/skills/ti-guides/references/coding-best-practices.md +1 -2
  32. package/skills/ti-guides/references/style-and-conventions.md +1 -2
  33. package/skills/ti-howtos/references/debugging-profiling.md +1 -2
  34. package/skills/ti-howtos/references/location-and-maps.md +1 -2
  35. package/skills/ti-howtos/references/using-modules.md +1 -2
  36. package/skills/ti-howtos/references/web-content-integration.md +1 -2
  37. package/skills/ti-howtos/references/webpack-build-pipeline.md +1 -2
  38. package/skills/ti-ui/references/listviews-and-performance.md +5 -10
  39. package/skills/ti-ui/references/orientation.md +1 -2
@@ -1,7 +1,6 @@
1
1
  # Migrating feedback surfaces
2
2
 
3
- Migrate semantics, not proxy names. Replacing every native dialog with the same
4
- custom modal preserves the original design problem.
3
+ Migrate semantics, not proxy names. Replacing every native dialog with the same custom modal preserves the original design problem.
5
4
 
6
5
  ## Contents
7
6
 
@@ -21,9 +20,7 @@ Search the application for:
21
20
  rg -n "createAlertDialog|createOptionDialog|createNotification|Toast|toast|snackbar|overlay" app/
22
21
  ```
23
22
 
24
- Also inspect helpers that wrap these calls, XML overlays, controller timers,
25
- global events, and callbacks that can present UI indirectly. Record for every
26
- occurrence:
23
+ Also inspect helpers that wrap these calls, XML overlays, controller timers, global events, and callbacks that can present UI indirectly. Record for every occurrence:
27
24
 
28
25
  - trigger and current message;
29
26
  - success, information, warning, error, confirmation, or choice;
@@ -33,8 +30,7 @@ occurrence:
33
30
  - callback side effects and cancellation behavior;
34
31
  - owning window and cleanup path.
35
32
 
36
- Do not implement the replacement until every occurrence has a semantic target
37
- from `feedback-surfaces.md`.
33
+ Do not implement the replacement until every occurrence has a semantic target from `feedback-surfaces.md`.
38
34
 
39
35
  ## Classify before replacing
40
36
 
@@ -47,13 +43,9 @@ Use these defaults:
47
43
  - uncommon irreversible decision → destructive Dialog;
48
44
  - several related actions or app-data choices → Bottom Sheet;
49
45
  - long structured content → scrollable sheet or dedicated screen;
50
- - OS permission, picker, share, date/time, biometric, or purchase flow → keep the
51
- system surface.
46
+ - OS permission, picker, share, date/time, biometric, or purchase flow → keep the system surface.
52
47
 
53
- Preserve domain behavior separately from presentation. Services return results
54
- or errors; the window/controller that owns visible context chooses the surface.
55
- Do not let a service create app-owned UI, especially before the root window
56
- exists.
48
+ Preserve domain behavior separately from presentation. Services return results or errors; the window/controller that owns visible context chooses the surface. Do not let a service create app-owned UI, especially before the root window exists.
57
49
 
58
50
  ## Migrate one window at a time
59
51
 
@@ -62,19 +54,15 @@ exists.
62
54
  3. Attach modal Widgets after the window exists.
63
55
  4. Route each old result to its classified surface.
64
56
  5. Call Widget `destroy()` from the window close cleanup.
65
- 6. Exercise success, failure, cancel, Back, backdrop, double tap, and consecutive
66
- presentation paths.
67
- 7. Remove the old dialog, local overlay, helper, timer, and listener after the
68
- migrated window passes verification.
57
+ 6. Exercise success, failure, cancel, Back, backdrop, double tap, and consecutive presentation paths.
58
+ 7. Remove the old dialog, local overlay, helper, timer, and listener after the migrated window passes verification.
69
59
  8. Commit the completed vertical slice before moving to the next window.
70
60
 
71
- Do not keep commented legacy implementations. Version control is the rollback
72
- mechanism; commented duplicates hide incomplete migrations and stale callbacks.
61
+ Do not keep commented legacy implementations. Version control is the rollback mechanism; commented duplicates hide incomplete migrations and stale callbacks.
73
62
 
74
63
  ## Deliberate silence
75
64
 
76
- Cancellation or an unknowable result can be a complete, intentional outcome.
77
- Model it explicitly and do not infer a message from falsy values.
65
+ Cancellation or an unknowable result can be a complete, intentional outcome. Model it explicitly and do not infer a message from falsy values.
78
66
 
79
67
  Example contract for an exported file:
80
68
 
@@ -103,9 +91,7 @@ function handleSaveResult(error, result) {
103
91
  }
104
92
  ```
105
93
 
106
- Do not add "Cancelled" for `saved === false`. Do not claim success for
107
- `saved === null`. Cover both branches with tests so a future fallback does not
108
- erase the intended silence.
94
+ Do not add "Cancelled" for `saved === false`. Do not claim success for `saved === null`. Cover both branches with tests so a future fallback does not erase the intended silence.
109
95
 
110
96
  ## Contract tests
111
97
 
@@ -114,8 +100,7 @@ Add repository-appropriate static or unit tests for:
114
100
  - all Widget folders, manifests, XML views, controllers, and dependency entries;
115
101
  - each public method documented in `feedback-widget-contracts.md`;
116
102
  - the expected Widget declared in every migrated window;
117
- - absence of app-owned `Ti.UI.createAlertDialog` and
118
- `Ti.UI.createOptionDialog` defaults;
103
+ - absence of app-owned `Ti.UI.createAlertDialog` and `Ti.UI.createOptionDialog` defaults;
119
104
  - removal of the previous local Snackbar/overlay and timer;
120
105
  - Snackbar replacement and timer reset;
121
106
  - Dialog and Bottom Sheet FIFO ordering;
@@ -124,18 +109,15 @@ Add repository-appropriate static or unit tests for:
124
109
  - cleanup of active and queued presentations;
125
110
  - explicit silence for cancel and indeterminate save results.
126
111
 
127
- Do not enforce blanket bans on native system surfaces. A remaining native call
128
- must be tied to an OS-owned interaction or documented fallback.
112
+ Do not enforce blanket bans on native system surfaces. A remaining native call must be tied to an OS-owned interaction or documented fallback.
129
113
 
130
114
  ## Delivery verification
131
115
 
132
- Run the project's real commands rather than assuming names. A complete migration
133
- normally includes:
116
+ Run the project's real commands rather than assuming names. A complete migration normally includes:
134
117
 
135
118
  1. lint with zero errors and no new warnings;
136
119
  2. unit and contract tests with no new failures;
137
- 3. PurgeTSS generation when detected, followed by inspection of unused or
138
- unsupported classes at the end of `app.tss`;
120
+ 3. PurgeTSS generation when detected, followed by inspection of unused or unsupported classes at the end of `app.tss`;
139
121
  4. Alloy compilation for Android and iOS;
140
122
  5. native builds for every supported platform;
141
123
  6. manual checks in light, dark, and system appearance;
@@ -144,9 +126,7 @@ normally includes:
144
126
  9. VoiceOver and TalkBack focus/traversal checks;
145
127
  10. consecutive presentation and window-close cleanup checks.
146
128
 
147
- Record pre-existing failures before migration and require the final run to add
148
- none. Build artifacts are not proof of usable modal behavior; perform the manual
149
- interaction checks on device or simulator.
129
+ Record pre-existing failures before migration and require the final run to add none. Build artifacts are not proof of usable modal behavior; perform the manual interaction checks on device or simulator.
150
130
 
151
131
  ## When to share Widgets between apps
152
132
 
@@ -157,9 +137,7 @@ Extract or copy a Widget into another app only when:
157
137
  - appearance depends on a documented semantic-token contract;
158
138
  - platform and minimum Titanium/Alloy versions are declared;
159
139
  - lifecycle and accessibility tests travel with it;
160
- - at least two apps need the same behavior, or one app has a clear portability
161
- requirement.
140
+ - at least two apps need the same behavior, or one app has a clear portability requirement.
162
141
 
163
- Do not extract merely because a view appeared three times. Extract because the
164
- boundary is independently understandable, testable, and maintainable.
142
+ Do not extract merely because a view appeared three times. Extract because the boundary is independently understandable, testable, and maintainable.
165
143
 
@@ -1,7 +1,6 @@
1
1
  # Feedback surfaces and app-owned UI
2
2
 
3
- Use this guide before choosing a Titanium proxy or drawing a component. The
4
- surface follows the meaning of the event: style comes afterwards.
3
+ Use this guide before choosing a Titanium proxy or drawing a component. The surface follows the meaning of the event: style comes afterwards.
5
4
 
6
5
  ## Contents
7
6
 
@@ -21,12 +20,9 @@ Classify the event in this order:
21
20
  3. **Recovery**: is the action reversible or is data at risk?
22
21
  4. **Location**: does the message belong to a field, a screen, or the whole app?
23
22
  5. **Persistence**: is it transient, persistent until state changes, or modal?
24
- 6. **Choice shape**: is there one acknowledgement, a binary decision, or a list
25
- of related actions?
23
+ 6. **Choice shape**: is there one acknowledgement, a binary decision, or a list of related actions?
26
24
 
27
- Do not begin with "which native dialog can display this string?" That turns
28
- different meanings into the same interruption and makes the app feel visually
29
- inconsistent.
25
+ Do not begin with "which native dialog can display this string?" That turns different meanings into the same interruption and makes the app feel visually inconsistent.
30
26
 
31
27
  ## Feedback scale
32
28
 
@@ -46,20 +42,13 @@ inconsistent.
46
42
  | No content yet | Empty State inside the screen | This is screen state, not transient feedback |
47
43
  | Initial or blocking work | Loading/Progress state in context | Communicates progress without inventing a message |
48
44
 
49
- Reserve Dialogs for critical information. Do not use them merely because they
50
- are easy to create. If an action is common and undoable, prefer immediate
51
- execution plus Undo over confirmation.
45
+ Reserve Dialogs for critical information. Do not use them merely because they are easy to create. If an action is common and undoable, prefer immediate execution plus Undo over confirmation.
52
46
 
53
47
  ### Snackbar versus Toast
54
48
 
55
- For app-owned foreground feedback, standardize on Snackbar. It supports the
56
- app's semantic colors, accessibility, safe-area positioning, duration policy,
57
- and one optional recovery action. Do not maintain both a custom Toast and a
58
- Snackbar for the same job.
49
+ For app-owned foreground feedback, standardize on Snackbar. It supports the app's semantic colors, accessibility, safe-area positioning, duration policy, and one optional recovery action. Do not maintain both a custom Toast and a Snackbar for the same job.
59
50
 
60
- A platform Toast can remain only when the operating system owns the behavior or
61
- when a documented platform fallback is necessary. It is not the default design
62
- surface.
51
+ A platform Toast can remain only when the operating system owns the behavior or when a documented platform fallback is necessary. It is not the default design surface.
63
52
 
64
53
  ### Banner versus Snackbar
65
54
 
@@ -69,17 +58,13 @@ surface.
69
58
 
70
59
  ### Bottom Sheet versus Dialog
71
60
 
72
- - Use Bottom Sheet for related choices: sorting, exporting, selecting a category,
73
- or choosing an action for an item.
61
+ - Use Bottom Sheet for related choices: sorting, exporting, selecting a category, or choosing an action for an item.
74
62
  - Use Dialog for acknowledgement or a consequential confirm/cancel decision.
75
- - Move long prose, structured data, search, or complex input into a sheet or
76
- dedicated screen.
63
+ - Move long prose, structured data, search, or complex input into a sheet or dedicated screen.
77
64
 
78
65
  ## App-owned versus system-owned
79
66
 
80
- Recreate and brand a surface only when the app owns its content and behavior.
81
- Keep the platform UI when the system owns trust, permissions, identity, files,
82
- or another protected workflow.
67
+ Recreate and brand a surface only when the app owns its content and behavior. Keep the platform UI when the system owns trust, permissions, identity, files, or another protected workflow.
83
68
 
84
69
  | Keep native/system-owned | May be app-owned and styled |
85
70
  | --- | --- |
@@ -91,43 +76,29 @@ or another protected workflow.
91
76
  | Biometric authentication prompt | Banners and inline validation |
92
77
  | Keyboard, autofill, purchases, notifications, and OS settings | App-specific onboarding or education |
93
78
 
94
- An app may explain why a system surface is about to appear, but it must not
95
- imitate the trusted system prompt. Use the official Titanium API or native module
96
- for the system-owned part.
79
+ An app may explain why a system surface is about to appear, but it must not imitate the trusted system prompt. Use the official Titanium API or native module for the system-owned part.
97
80
 
98
- Cancellation is often a normal system outcome. Do not turn every cancellation
99
- into an error, a "Cancelled" message, or an unsupported success claim. Document
100
- silence explicitly at the call site when it is meaningful.
81
+ Cancellation is often a normal system outcome. Do not turn every cancellation into an error, a "Cancelled" message, or an unsupported success claim. Document silence explicitly at the call site when it is meaningful.
101
82
 
102
83
  ## What to standardize next
103
84
 
104
85
  After Snackbar, Dialog, and Bottom Sheet, the highest-value shared patterns are:
105
86
 
106
87
  1. **Banner / Inline Notice** for persistent app state.
107
- 2. **Loading / Progress wrapper** that uses the native activity indicator but
108
- standardizes placement, text, blocking behavior, and cleanup.
88
+ 2. **Loading / Progress wrapper** that uses the native activity indicator but standardizes placement, text, blocking behavior, and cleanup.
109
89
  3. **Empty / Error State** for consistent screen-level recovery.
110
90
  4. **Field Validation** for message placement, focus, accessibility, and colors.
111
91
 
112
- Standardize buttons, cards, badges, chips, skeletons, and coach marks only when
113
- real product repetition exposes a stable contract. A visual resemblance alone
114
- does not justify a Widget.
92
+ Standardize buttons, cards, badges, chips, skeletons, and coach marks only when real product repetition exposes a stable contract. A visual resemblance alone does not justify a Widget.
115
93
 
116
94
  ## Phone, tablet, and accessibility
117
95
 
118
- - On phones, present contextual choices from the bottom and keep touch targets
119
- reachable.
120
- - On tablets and large screens, use a centered, width-limited action surface or
121
- a platform-appropriate anchored presentation; do not stretch phone geometry
122
- edge to edge.
123
- - Respect safe areas, bottom navigation, orientation, split screen, text scaling,
124
- and localized strings.
125
- - Announce transient feedback appropriately and move accessibility focus into a
126
- modal surface when it opens.
127
- - While a modal is active, prevent interaction with and accessibility traversal
128
- into the underlying content. Restore the exact previous state on close.
129
- - Back, backdrop, Cancel, and destructive actions must have predictable semantics
130
- and must never execute callbacks more than once.
96
+ - On phones, present contextual choices from the bottom and keep touch targets reachable.
97
+ - On tablets and large screens, use a centered, width-limited action surface or a platform-appropriate anchored presentation; do not stretch phone geometry edge to edge.
98
+ - Respect safe areas, bottom navigation, orientation, split screen, text scaling, and localized strings.
99
+ - Announce transient feedback appropriately and move accessibility focus into a modal surface when it opens.
100
+ - While a modal is active, prevent interaction with and accessibility traversal into the underlying content. Restore the exact previous state on close.
101
+ - Back, backdrop, Cancel, and destructive actions must have predictable semantics and must never execute callbacks more than once.
131
102
 
132
103
  ## References
133
104
 
@@ -1,7 +1,6 @@
1
1
  # Contracts for feedback Widgets
2
2
 
3
- Use these contracts for app-owned Snackbar, Dialog, and Bottom Sheet surfaces in
4
- Alloy. Namespaces and visual tokens belong to each app; behavior stays stable.
3
+ Use these contracts for app-owned Snackbar, Dialog, and Bottom Sheet surfaces in Alloy. Namespaces and visual tokens belong to each app; behavior stays stable.
5
4
 
6
5
  ## Contents
7
6
 
@@ -15,12 +14,7 @@ Alloy. Namespaces and visual tokens belong to each app; behavior stays stable.
15
14
 
16
15
  ## Boundary and registration
17
16
 
18
- Implement each surface as an independent Alloy Widget under `app/widgets/`.
19
- Each Widget owns its XML, controller, optional styles, assets, state, listeners,
20
- timers, and `widget.json`. Keep them independent from any third-party component
21
- library — including TiKit, the Alloy/PurgeTSS component set. A feedback surface
22
- must not require one to work, and must not be folded into one: its value comes
23
- from being installable and testable on its own.
17
+ Implement each surface as an independent Alloy Widget under `app/widgets/`. Each Widget owns its XML, controller, optional styles, assets, state, listeners, timers, and `widget.json`. Keep them independent from any third-party component library — including TiKit, the Alloy/PurgeTSS component set. A feedback surface must not require one to work, and must not be folded into one: its value comes from being installable and testable on its own.
24
18
 
25
19
  Register every Widget in `app/config.json`:
26
20
 
@@ -34,11 +28,9 @@ Register every Widget in `app/config.json`:
34
28
  }
35
29
  ```
36
30
 
37
- Use the app's reverse-domain namespace. The dependency key must match the `id`
38
- in that Widget's `widget.json`.
31
+ Use the app's reverse-domain namespace. The dependency key must match the `id` in that Widget's `widget.json`.
39
32
 
40
- Declare Widgets in XML, normally as the last visual children of the owning
41
- window so overlays render above screen content:
33
+ Declare Widgets in XML, normally as the last visual children of the owning window so overlays render above screen content:
42
34
 
43
35
  ```xml
44
36
  <Widget id="snackbar" src="com.example.ui.snackbar" />
@@ -46,8 +38,7 @@ window so overlays render above screen content:
46
38
  <Widget id="bottomSheet" src="com.example.ui.bottomsheet" />
47
39
  ```
48
40
 
49
- Build the stable proxy tree in XML. JavaScript may update properties and supply
50
- `ListView` data; it must not reconstruct the complete surface imperatively.
41
+ Build the stable proxy tree in XML. JavaScript may update properties and supply `ListView` data; it must not reconstruct the complete surface imperatively.
51
42
 
52
43
  ## Snackbar
53
44
 
@@ -68,12 +59,10 @@ $.snackbar.destroy()
68
59
  Contract:
69
60
 
70
61
  - A new message replaces the visible message and restarts the timer.
71
- - Default `duration` is 4500 ms; `duration: 0` remains visible until an action,
72
- `dismiss()`, replacement, or destruction.
62
+ - Default `duration` is 4500 ms; `duration: 0` remains visible until an action, `dismiss()`, replacement, or destruction.
73
63
  - Allow at most one text action, such as Undo.
74
64
  - Invoke `onAction` once, then close the Snackbar.
75
- - Invoke `onDismiss` once with the reason `timeout`, `action`, `replaced`,
76
- `programmatic`, or `destroy`.
65
+ - Invoke `onDismiss` once with the reason `timeout`, `action`, `replaced`, `programmatic`, or `destroy`.
77
66
  - Clear the old timer before replacement and on every close path.
78
67
  - Position above bottom navigation and inside the current safe area.
79
68
  - Queueing Snackbars is not the default. The newest relevant message wins.
@@ -100,20 +89,15 @@ $.dialog.destroy()
100
89
 
101
90
  Contract:
102
91
 
103
- - Without `cancelTitle`, present an acknowledgement. With it, present a
104
- confirmation.
92
+ - Without `cancelTitle`, present an acknowledgement. With it, present a confirmation.
105
93
  - Enqueue additional `show()` calls FIFO. Never stack two Dialogs visually.
106
94
  - Disable both buttons on the first accepted tap.
107
95
  - Invoke `onConfirm` or `onCancel` at most once; never both.
108
- - Cancel button, Android Back, or allowed backdrop dismissal invokes `onCancel`.
109
- Android Back closes an acknowledgement as its single dismissal action.
96
+ - Cancel button, Android Back, or allowed backdrop dismissal invokes `onCancel`. Android Back closes an acknowledgement as its single dismissal action.
110
97
  - A destructive confirmation must not close from a backdrop tap.
111
- - `dismiss('programmatic')` closes without treating the operation as a user
112
- confirmation or cancellation.
113
- - `destroy()` clears the active request and queue without running business
114
- callbacks.
115
- - Use platform-familiar safe/cancel ordering and a distinct destructive role;
116
- do not hard-code one platform's button order for both.
98
+ - `dismiss('programmatic')` closes without treating the operation as a user confirmation or cancellation.
99
+ - `destroy()` clears the active request and queue without running business callbacks.
100
+ - Use platform-familiar safe/cancel ordering and a distinct destructive role; do not hard-code one platform's button order for both.
117
101
 
118
102
  ## Bottom Sheet
119
103
 
@@ -142,60 +126,40 @@ $.bottomSheet.destroy()
142
126
 
143
127
  Contract:
144
128
 
145
- - Render items with a fixed `ListView` template and data objects. Support long
146
- lists, disabled rows, optional subtitles/icons, and a selected marker.
129
+ - Render items with a fixed `ListView` template and data objects. Support long lists, disabled rows, optional subtitles/icons, and a selected marker.
147
130
  - Enqueue additional `show()` calls FIFO. Never stack sheets.
148
- - Accept the first enabled selection only, invoke `onSelect(item)` once, and
149
- close.
131
+ - Accept the first enabled selection only, invoke `onSelect(item)` once, and close.
150
132
  - Backdrop, Android Back, Cancel, or `dismiss('cancel')` invokes `onCancel` once.
151
- - Other programmatic dismissal and `destroy()` do not imply cancellation and do
152
- not execute business callbacks.
153
- - Present from the bottom on phones. On tablets and large screens, use a centered,
154
- width-limited action surface. Reserve `anchor` for a future anchored variant;
155
- do not expose behavior that is not implemented.
133
+ - Other programmatic dismissal and `destroy()` do not imply cancellation and do not execute business callbacks.
134
+ - Present from the bottom on phones. On tablets and large screens, use a centered, width-limited action surface. Reserve `anchor` for a future anchored variant; do not expose behavior that is not implemented.
156
135
 
157
136
  ## Shared lifecycle contract
158
137
 
159
- - Prefer one instance of each needed Widget per window. Add a global coordinator
160
- only after real cross-window requirements exist.
161
- - Call `attach(window)` after the host window/controller exists. Call `destroy()`
162
- from the host's close cleanup.
163
- - Make `destroy()` idempotent. Remove listeners, clear timers, cancel pending
164
- animation callbacks, clear queues, and release callback references.
165
- - Guard every asynchronous completion with the current presentation generation
166
- so a stale timer or animation cannot dismiss a newer request.
138
+ - Prefer one instance of each needed Widget per window. Add a global coordinator only after real cross-window requirements exist.
139
+ - Call `attach(window)` after the host window/controller exists. Call `destroy()` from the host's close cleanup.
140
+ - Make `destroy()` idempotent. Remove listeners, clear timers, cancel pending animation callbacks, clear queues, and release callback references.
141
+ - Guard every asynchronous completion with the current presentation generation so a stale timer or animation cannot dismiss a newer request.
167
142
  - Consume backdrop events and prevent them from bubbling to underlying controls.
168
- - Save the host's previous accessibility state, exclude underlying content while
169
- modal, move focus to the surface, and restore the saved state on close.
170
- - Keep localized copy outside the Widget. Pass strings and business callbacks in
171
- the public API.
172
- - Keep business logic out of the Widget. It reports a choice; the host performs
173
- domain work.
174
- - Verify every callback path for exactly-once behavior: action, confirm, cancel,
175
- Back, backdrop, timeout, replacement, programmatic dismissal, and destruction.
143
+ - Save the host's previous accessibility state, exclude underlying content while modal, move focus to the surface, and restore the saved state on close.
144
+ - Keep localized copy outside the Widget. Pass strings and business callbacks in the public API.
145
+ - Keep business logic out of the Widget. It reports a choice; the host performs domain work.
146
+ - Verify every callback path for exactly-once behavior: action, confirm, cancel, Back, backdrop, timeout, replacement, programmatic dismissal, and destruction.
176
147
 
177
148
  ## PurgeTSS integration
178
149
 
179
- When `purgetss/` or `purgetss/config.cjs` exists, load the `purgetss` skill before
180
- writing styles. `ti-expert` decides the component boundary; `purgetss` decides
181
- the verified utilities and configuration.
150
+ When `purgetss/` or `purgetss/config.cjs` exists, load the `purgetss` skill before writing styles. `ti-expert` decides the component boundary; `purgetss` decides the verified utilities and configuration.
182
151
 
183
152
  Apply these architectural rules:
184
153
 
185
154
  - Set PurgeTSS `options.widgets` to `true` so Widget XML is scanned.
186
155
  - Express stable anatomy and utility classes in Widget XML.
187
- - Use semantic color names for surfaces, text, borders, accent, overlay, success,
188
- warning, and error. Let Titanium resolve light/dark variants.
156
+ - Use semantic color names for surfaces, text, borders, accent, overlay, success, warning, and error. Let Titanium resolve light/dark variants.
189
157
  - Do not edit generated `app/styles/app.tss`.
190
- - Use `widget.tss` only for properties that have no verified utility or that are
191
- inherently specific to the Widget.
192
- - Declare animations as XML `Animation` proxies using `purgetss.ui`. Use explicit
193
- `open()` and `close()` calls instead of toggle behavior.
194
- - After generation, inspect the final `app.tss` section for unused or unsupported
195
- classes and resolve every new entry.
158
+ - Use `widget.tss` only for properties that have no verified utility or that are inherently specific to the Widget.
159
+ - Declare animations as XML `Animation` proxies using `purgetss.ui`. Use explicit `open()` and `close()` calls instead of toggle behavior.
160
+ - After generation, inspect the final `app.tss` section for unused or unsupported classes and resolve every new entry.
196
161
 
197
- Do not copy class inventories into this skill and do not guess Tailwind-like
198
- names. The installed PurgeTSS skill remains the source of truth.
162
+ Do not copy class inventories into this skill and do not guess Tailwind-like names. The installed PurgeTSS skill remains the source of truth.
199
163
 
200
164
  ## Widget, Require, state, or native UI
201
165
 
@@ -207,7 +171,5 @@ names. The installed PurgeTSS skill remains the source of truth.
207
171
  | TSS or PurgeTSS utilities | Repeated visual treatment has no behavior, state, or lifecycle |
208
172
  | Native/system UI | The operating system owns permissions, trust, files, sharing, identity, purchases, or another protected flow |
209
173
 
210
- Usage count is evidence, not a threshold. A component can deserve a Widget on
211
- its first use if it has a stable portable API and non-trivial lifecycle; three
212
- similar labels still do not deserve one.
174
+ Usage count is evidence, not a threshold. A component can deserve a Widget on its first use if it has a stable portable API and non-trivial lifecycle; three similar labels still do not deserve one.
213
175