terrier-engine 4.0.21 → 4.1.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.
package/app.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  import { Logger } from "tuff-core/logging"
2
- import {Part, PartParent} from "tuff-core/parts"
3
- import {TerrierPart} from "./parts"
2
+ import {Part, PartConstructor, PartParent} from "tuff-core/parts"
3
+ import TerrierPart from "./parts/terrier-part"
4
4
  import Tooltips from "./tooltips"
5
5
  import Lightbox from "./lightbox"
6
+ import Theme, {ThemeType} from "./theme"
7
+ import {ModalPart, ModalStackPart} from "./modals"
8
+ import {OverlayLayerType, OverlayPart} from "./overlays"
6
9
 
7
10
  // @ts-ignore
8
11
  import logoUrl from './images/optimized/terrier-hub-logo-light.svg'
9
- import Theme, {ThemeType} from "./theme"
10
- import {ModalPart, ModalStackPart} from "./modals"
11
- import {OverlayLayer, OverlayPart} from "./overlays"
12
12
 
13
13
  const log = new Logger('App')
14
14
  Logger.level = 'info'
@@ -50,36 +50,50 @@ export abstract class TerrierApp<
50
50
 
51
51
  /// Overlays
52
52
 
53
- makeOverlay<OverlayType extends Part<StateType>, StateType>(
53
+ addOverlay<OverlayType extends Part<StateType>, StateType extends {}>(
54
54
  constructor: { new(p: PartParent, id: string, state: StateType): OverlayType; },
55
55
  state: StateType,
56
- layer: OverlayLayer
57
- ): OverlayType {
58
- return this.overlayPart.makeLayer(constructor, state, layer)
56
+ type: OverlayLayerType
57
+ ) {
58
+ return this.overlayPart.pushLayer(constructor, state, type)
59
59
  }
60
60
 
61
- clearOverlay(layer: OverlayLayer) {
62
- this.overlayPart.clearLayer(layer)
63
- this.lastDropdownTarget = undefined
61
+ removeOverlay<StateType extends {}>(state: StateType): boolean {
62
+ return this.overlayPart.removeLayer(state)
63
+ }
64
+
65
+ popOverlay(type?: OverlayLayerType) {
66
+ this.overlayPart.popLayer(type)
64
67
  }
65
68
 
66
69
  clearOverlays() {
67
70
  this.overlayPart.clearAll()
68
71
  }
69
72
 
73
+ removeDropdown<StateType extends {}>(state: StateType): boolean {
74
+ this.lastDropdownTarget = undefined
75
+ return this.overlayPart.removeLayer(state)
76
+ }
77
+
78
+ clearDropdowns() {
79
+ this.lastDropdownTarget = undefined
80
+ this.popOverlay('dropdown')
81
+ }
82
+
70
83
 
71
84
  lastDropdownTarget?: HTMLElement
72
85
 
73
86
 
74
87
  /// Modals
75
88
 
76
- showModal<ModalType extends ModalPart<StateType, TThemeType, TSelf, TTheme>, StateType>(constructor: { new(p: PartParent, id: string, state: StateType): ModalType; }, state: StateType): ModalType {
77
- const modalStack =
78
- (this.overlayPart.parts.modal as ModalStackPart<TThemeType, TSelf, TTheme, ModalType>)
79
- ?? this.makeOverlay(ModalStackPart, {}, 'modal')
89
+ showModal<ModalType extends ModalPart<StateType, TThemeType, TSelf, TTheme>, StateType>(
90
+ constructor: PartConstructor<ModalType, StateType>,
91
+ state: StateType
92
+ ): ModalType {
93
+ const modalStack = this.overlayPart.getOrCreateLayer(ModalStackPart, {}, 'modal')
80
94
  const modal = modalStack.pushModal(constructor, state)
81
95
  modalStack.dirty()
82
- return modal
96
+ return modal as ModalType
83
97
  }
84
98
 
85
99
 
package/dropdowns.ts CHANGED
@@ -3,10 +3,10 @@ import { untypedKey } from "tuff-core/messages"
3
3
  import { unique } from "tuff-core/arrays"
4
4
  import {PartTag, StatelessPart} from "tuff-core/parts"
5
5
  import Overlays from "./overlays"
6
- import {TerrierPart} from "./parts"
6
+ import TerrierPart from "./parts/terrier-part"
7
7
  import Objects from "tuff-core/objects"
8
8
  import Theme, {Action, ThemeType} from "./theme"
9
- import {TerrierApp} from "./app";
9
+ import {TerrierApp} from "./app"
10
10
 
11
11
  const log = new Logger('Dropdowns')
12
12
 
@@ -17,7 +17,7 @@ const clearDropdownKey = untypedKey()
17
17
  * Subclasses must implement the `renderContent()` method to render the dropdown content.
18
18
  */
19
19
  export abstract class Dropdown<
20
- TState,
20
+ TState extends {},
21
21
  TThemeType extends ThemeType,
22
22
  TApp extends TerrierApp<TThemeType, TApp, TTheme>,
23
23
  TTheme extends Theme<TThemeType>
@@ -29,12 +29,20 @@ export abstract class Dropdown<
29
29
  return ['tt-dropdown', ...super.parentClasses]
30
30
  }
31
31
 
32
+ /**
33
+ * Override and return true to have the dropdown close when the user clicks anywhere outside of it.
34
+ */
35
+ get autoClose(): boolean {
36
+ return false
37
+ }
38
+
32
39
  // the computed absolute position of the
33
40
  left = 0
34
41
  top = 0
35
42
 
36
43
  async init() {
37
- this.onClick(clearDropdownKey, _ => {
44
+ this.onClick(clearDropdownKey, m => {
45
+ log.info("Clearing dropdown", m)
38
46
  this.clear()
39
47
  })
40
48
  }
@@ -44,11 +52,15 @@ export abstract class Dropdown<
44
52
  */
45
53
  clear() {
46
54
  log.info("Clearing dropdown")
47
- this.app.clearOverlay('dropdown')
55
+ this.app.removeDropdown(this.state)
48
56
  }
49
57
 
50
58
  render(parent: PartTag) {
51
- parent.div('.dropdown-content', content => {
59
+ if (this.autoClose) {
60
+ parent.div('.tt-dropdown-backdrop')
61
+ .emitClick(clearDropdownKey)
62
+ }
63
+ parent.div('.tt-dropdown-content', content => {
52
64
  this.renderContent(content)
53
65
  })
54
66
  }
@@ -71,7 +83,7 @@ export abstract class Dropdown<
71
83
  }
72
84
 
73
85
  update(_elem: HTMLElement) {
74
- const content = _elem.querySelector('.dropdown-content')
86
+ const content = _elem.querySelector('.tt-dropdown-content')
75
87
  if (this.anchorTarget && content) {
76
88
  log.info(`Anchoring dropdown`, content, this.anchorTarget)
77
89
  Overlays.anchorElement(content as HTMLElement, this.anchorTarget)
@@ -91,6 +103,10 @@ export class ActionsDropdown<
91
103
  > extends Dropdown<Array<Action<TThemeType>>, TThemeType, TApp, TTheme> {
92
104
 
93
105
 
106
+ get autoClose(): boolean {
107
+ return true
108
+ }
109
+
94
110
  get parentClasses(): Array<string> {
95
111
  return ['tt-actions-dropdown', ...super.parentClasses]
96
112
  }
@@ -101,7 +117,7 @@ export class ActionsDropdown<
101
117
  const keys = unique(this.state.map(action => action.click?.key).filter(Objects.notNull))
102
118
  for (const key of keys) {
103
119
  this.onClick(key, m => {
104
- this.app.clearOverlay('dropdown')
120
+ this.clear()
105
121
  log.info(`Re-emitting ${key.id} message`, m, this.parentPart)
106
122
  if (this.parentPart) {
107
123
  this.parentPart.emit('click', key, m.event, m.data)
package/forms.ts ADDED
@@ -0,0 +1,33 @@
1
+ import {SelectOptions} from "tuff-core/forms"
2
+ import {strings} from "tuff-core"
3
+
4
+ ////////////////////////////////////////////////////////////////////////////////
5
+ // Options
6
+ ////////////////////////////////////////////////////////////////////////////////
7
+
8
+ /**
9
+ * Computes a `SelectOptions` array by titleizing the values in a plain string array.
10
+ * @param opts
11
+ */
12
+ function titleizeOptions(opts: string[], blank?: string): SelectOptions {
13
+ const out = opts.map(c => {
14
+ return {value: c, title: strings.titleize(c)}
15
+ })
16
+ if (blank != undefined) { // don't test length, allow it to be a blank string
17
+ out.unshift({title: blank, value: ''})
18
+ }
19
+ return out
20
+ }
21
+
22
+
23
+ ////////////////////////////////////////////////////////////////////////////////
24
+ // Export
25
+ ////////////////////////////////////////////////////////////////////////////////
26
+
27
+ const Forms = {
28
+ titleizeOptions
29
+ }
30
+
31
+ export default Forms
32
+
33
+
package/fragments.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {PartTag} from "tuff-core/parts"
2
2
  import {AnchorTagAttrs, HtmlParentTag} from "tuff-core/html"
3
3
  import Theme, {Action, Packet, ThemeType} from "./theme"
4
- import {ActionLevel, PanelActions} from "./parts"
4
+ import {ActionLevel, PanelActions} from "./parts/content-part"
5
5
 
6
6
  /**
7
7
  * Base class for Panel and Card fragment builders.
@@ -102,16 +102,18 @@ export class PanelFragment<TT extends ThemeType> extends ContentFragment<TT> {
102
102
  * Render the primary and secondary actions to the bottom of a panel
103
103
  * @param panel the .panel container
104
104
  * @param actions the actions
105
+ * @param theme the theme with which to render actions
105
106
  */
106
107
  function panelActions<TT extends ThemeType>(panel: PartTag, actions: PanelActions<TT>, theme: Theme<TT>) {
107
108
  if (actions.primary.length || actions.secondary.length) {
108
109
  panel.div('.panel-actions', actionsContainer => {
109
- actionsContainer.div('.secondary-actions', secondaryContainer => {
110
- theme.renderActions(secondaryContainer, actions.secondary, {iconColor: 'white', defaultClass: 'link'})
111
- })
112
- actionsContainer.div('.primary-actions', primaryContainer => {
113
- theme.renderActions(primaryContainer, actions.primary, {iconColor: 'white'})
114
- })
110
+ for (const level of ['secondary', 'primary'] as const) {
111
+ const levelActions = actions[level]
112
+ if (!levelActions?.length) continue;
113
+ actionsContainer.div(`.${level}-actions`, container => {
114
+ theme.renderActions(container, levelActions, { iconColor: 'white', defaultClass: level })
115
+ })
116
+ }
115
117
  })
116
118
  }
117
119
  }
package/glyps.ts CHANGED
@@ -1,6 +1,6 @@
1
- // This file was automatically generated by glyps:compile on 05/15/23 7:41 PM, DO NOT MANUALLY EDIT!
1
+ // This file was automatically generated by glyps:compile on 06/01/23 10:19 AM, DO NOT MANUALLY EDIT!
2
2
 
3
- const names = ['glyp-abacus', 'glyp-account', 'glyp-accounts_payable', 'glyp-accounts_receivable', 'glyp-action_log', 'glyp-activate', 'glyp-active', 'glyp-activity_high', 'glyp-activity_low', 'glyp-activity_medium', 'glyp-activity_none', 'glyp-address1', 'glyp-adjustment', 'glyp-admin', 'glyp-administration', 'glyp-air_freshener', 'glyp-alert', 'glyp-align_horizontal', 'glyp-align_vertical', 'glyp-anchor', 'glyp-announcement', 'glyp-app_update', 'glyp-append_selection', 'glyp-appointment', 'glyp-appointment_setup', 'glyp-archive', 'glyp-arrow_down', 'glyp-arrow_left', 'glyp-arrow_right', 'glyp-arrow_transfer', 'glyp-arrow_up', 'glyp-ascending', 'glyp-attachment', 'glyp-audit_analyzer', 'glyp-autopay', 'glyp-availability', 'glyp-background_batch', 'glyp-background_job', 'glyp-bait_for_demolition', 'glyp-bar_chart', 'glyp-barcode', 'glyp-bat_exclusion', 'glyp-bed_bug_fumigation', 'glyp-begin_service', 'glyp-belongs_to', 'glyp-billing', 'glyp-billing_office', 'glyp-billing_terms', 'glyp-billto', 'glyp-bioremediation', 'glyp-bird_exclusion', 'glyp-black_light', 'glyp-branch', 'glyp-branch_bats', 'glyp-branch_birds', 'glyp-branch_general', 'glyp-branch_irrigation', 'glyp-branch_landscape', 'glyp-branch_multi_housing', 'glyp-branch_office', 'glyp-branch_orders', 'glyp-branch_residential', 'glyp-branch_sales', 'glyp-branch_termites', 'glyp-branch_weeds', 'glyp-branch_wildlife', 'glyp-build', 'glyp-calculate', 'glyp-calendar', 'glyp-calendar_branch', 'glyp-calendar_map', 'glyp-calendar_rolling', 'glyp-calendar_share', 'glyp-calendar_snap', 'glyp-california', 'glyp-call', 'glyp-callback', 'glyp-camera', 'glyp-cancellation', 'glyp-cancelled', 'glyp-card_american_express', 'glyp-card_discover', 'glyp-card_mastercard', 'glyp-card_visa', 'glyp-catalog', 'glyp-caught', 'glyp-cert', 'glyp-check_all', 'glyp-check_in', 'glyp-check_in_service', 'glyp-checked', 'glyp-checked_empty', 'glyp-checkmark', 'glyp-checkmark_filled', 'glyp-checkout', 'glyp-chemical', 'glyp-chemical_authorization', 'glyp-chemical_backpack_sprayer', 'glyp-chemical_biological_controls', 'glyp-chemical_disinfectant', 'glyp-chemical_fertilizer', 'glyp-chemical_flying_insect_bait', 'glyp-chemical_fumigants', 'glyp-chemical_insect_aerosol', 'glyp-chemical_insect_bait', 'glyp-chemical_insect_dust', 'glyp-chemical_insect_granules', 'glyp-chemical_insect_spray', 'glyp-chemical_label', 'glyp-chemical_mole_bait', 'glyp-chemical_pest_bird_control', 'glyp-chemical_pheromone_products', 'glyp-chemical_power_sprayer', 'glyp-chemical_rodenticide_block', 'glyp-chemical_rodenticide_non_block', 'glyp-chemical_sds', 'glyp-chemical_tree_products', 'glyp-chemical_weed_control', 'glyp-chemical_wildlife_repellents', 'glyp-chemical_wildlife_toxicants', 'glyp-chevron_down', 'glyp-chevron_left', 'glyp-chevron_right', 'glyp-chevron_up', 'glyp-city', 'glyp-click', 'glyp-client_actions', 'glyp-client_pest_sightings', 'glyp-client_required', 'glyp-close', 'glyp-cloud', 'glyp-clypboard', 'glyp-clypedia', 'glyp-clypmart', 'glyp-code', 'glyp-code_details', 'glyp-collections', 'glyp-columns', 'glyp-comment', 'glyp-comment_filled', 'glyp-commission_origin', 'glyp-commissions', 'glyp-company_setup', 'glyp-compass', 'glyp-complete', 'glyp-complete_certificate', 'glyp-complete_enrollment', 'glyp-condition_appliance_machinery', 'glyp-condition_customer', 'glyp-condition_device', 'glyp-condition_door_window', 'glyp-condition_dumpster', 'glyp-condition_entry_point', 'glyp-condition_evidence', 'glyp-condition_exclusion', 'glyp-condition_exterior', 'glyp-condition_interior', 'glyp-condition_plumbing', 'glyp-condition_prep_storage', 'glyp-condition_rodent_evidence', 'glyp-condition_rodent_exclusion', 'glyp-condition_roof_ceiling', 'glyp-condition_structure', 'glyp-condition_supplies', 'glyp-condition_termites', 'glyp-condition_ventilation', 'glyp-condition_wall_floor', 'glyp-condition_wildlife', 'glyp-conditions', 'glyp-consolidate', 'glyp-construction', 'glyp-contract', 'glyp-contract_cancellation', 'glyp-contract_overview', 'glyp-conversation', 'glyp-copesan', 'glyp-copy', 'glyp-credit_memo', 'glyp-credit_non_revenue', 'glyp-credit_production', 'glyp-credit_prospect', 'glyp-credit_sales_bonus', 'glyp-crew', 'glyp-cumulative', 'glyp-cursor', 'glyp-custom_form', 'glyp-customer', 'glyp-customer_service', 'glyp-dashboard', 'glyp-database', 'glyp-dead_animal_removal', 'glyp-default', 'glyp-delete', 'glyp-demo_mode', 'glyp-descending', 'glyp-design', 'glyp-desktop', 'glyp-detail_report', 'glyp-developer', 'glyp-device', 'glyp-device_sync', 'glyp-differential', 'glyp-disable', 'glyp-disabled_filled', 'glyp-distribute_horizontal', 'glyp-distribute_vertical', 'glyp-division', 'glyp-document', 'glyp-documentation', 'glyp-documents', 'glyp-download', 'glyp-driving', 'glyp-duplicate', 'glyp-duplicate_location', 'glyp-duration', 'glyp-edit', 'glyp-email', 'glyp-employment', 'glyp-entertainment_public_venues', 'glyp-equipment_bear_trap', 'glyp-equipment_flying_insect_bait_station', 'glyp-equipment_flying_insect_light_trap', 'glyp-equipment_insect_monitor', 'glyp-equipment_lethal_animal_trap', 'glyp-equipment_live_animal_trap', 'glyp-equipment_live_rodent_trap', 'glyp-equipment_maintenance', 'glyp-equipment_map_viewer', 'glyp-equipment_maps', 'glyp-equipment_mosquito_trap', 'glyp-equipment_other', 'glyp-equipment_pheromone_trap', 'glyp-equipment_pick_up', 'glyp-equipment_rodent_bait', 'glyp-equipment_rodent_trap', 'glyp-equipment_termite_bait_station', 'glyp-equipment_termite_monitor', 'glyp-exclusion', 'glyp-expand', 'glyp-expiring', 'glyp-exterior', 'glyp-extras', 'glyp-facebook', 'glyp-farm', 'glyp-farm_grain_seed', 'glyp-fast_and_frequent', 'glyp-favorite', 'glyp-feedback', 'glyp-field_guide', 'glyp-field_training', 'glyp-file_blank', 'glyp-file_html', 'glyp-file_image', 'glyp-file_pdf', 'glyp-file_printable', 'glyp-file_spreadsheet', 'glyp-file_text', 'glyp-filter', 'glyp-finance', 'glyp-finding', 'glyp-folder', 'glyp-followup', 'glyp-food_bev_pharma', 'glyp-formula', 'glyp-fuel', 'glyp-fumigation', 'glyp-gain_loss', 'glyp-generate_invoices', 'glyp-generate_orders', 'glyp-geo', 'glyp-geo_heat_map', 'glyp-google', 'glyp-google_calendar', 'glyp-government', 'glyp-grain_seed', 'glyp-grid', 'glyp-grouping_combine', 'glyp-grouping_separate', 'glyp-has_many', 'glyp-health_care', 'glyp-heat_map', 'glyp-heat_treatment', 'glyp-help', 'glyp-hidden', 'glyp-honeybee_removal', 'glyp-housing', 'glyp-in_progress', 'glyp-incomplete_certificate', 'glyp-industrial', 'glyp-info', 'glyp-information_technology', 'glyp-inspect_map', 'glyp-inspections', 'glyp-insulation', 'glyp-interior', 'glyp-invoice', 'glyp-invoice_review', 'glyp-irrigation_install', 'glyp-irrigation_maintenance', 'glyp-items', 'glyp-job', 'glyp-justice', 'glyp-k9_inspection', 'glyp-key', 'glyp-label_bottom', 'glyp-label_left', 'glyp-label_right', 'glyp-label_top', 'glyp-labor', 'glyp-landscape', 'glyp-landscape_maintenance', 'glyp-laptop', 'glyp-lead', 'glyp-lead_listing', 'glyp-lead_source', 'glyp-leads_report', 'glyp-learning_hub', 'glyp-ledger', 'glyp-legal', 'glyp-license', 'glyp-lifetime', 'glyp-line_cap_arrow', 'glyp-line_cap_bar', 'glyp-line_cap_circle', 'glyp-line_cap_none', 'glyp-line_caps', 'glyp-line_style', 'glyp-link', 'glyp-location', 'glyp-location_charge', 'glyp-location_credit', 'glyp-location_kind', 'glyp-location_message', 'glyp-location_origin', 'glyp-location_tags', 'glyp-locations', 'glyp-locked', 'glyp-lodging', 'glyp-log_in', 'glyp-log_out', 'glyp-log_report', 'glyp-logbook', 'glyp-logbook_documents', 'glyp-lot_number', 'glyp-manager', 'glyp-map', 'glyp-markdown', 'glyp-market', 'glyp-materials', 'glyp-mattress_encasement', 'glyp-merge', 'glyp-message_billing', 'glyp-message_collections', 'glyp-message_complaint', 'glyp-message_misc', 'glyp-message_technician', 'glyp-messages', 'glyp-misc', 'glyp-miscellaneous', 'glyp-move_order', 'glyp-mowing', 'glyp-multi_housing', 'glyp-mute', 'glyp-navicon', 'glyp-new_location', 'glyp-no_charge', 'glyp-no_service', 'glyp-note', 'glyp-note_access', 'glyp-note_billing', 'glyp-note_collection', 'glyp-note_complaint', 'glyp-note_directions', 'glyp-note_focused', 'glyp-note_office', 'glyp-note_preservice', 'glyp-note_sales', 'glyp-note_service', 'glyp-notification', 'glyp-number', 'glyp-office', 'glyp-office_government', 'glyp-office_training', 'glyp-on_demand', 'glyp-on_demand_order', 'glyp-open', 'glyp-open_invoice', 'glyp-operations', 'glyp-options', 'glyp-order_actions', 'glyp-order_approved', 'glyp-order_batch', 'glyp-order_editor', 'glyp-order_pending', 'glyp-order_series', 'glyp-order_unapproved', 'glyp-org_structure', 'glyp-org_unit', 'glyp-org_unit_settings', 'glyp-origin', 'glyp-origin_client', 'glyp-origin_tech', 'glyp-outlook', 'glyp-overlap', 'glyp-password', 'glyp-past_due', 'glyp-paused', 'glyp-pay_brackets', 'glyp-payment', 'glyp-payment_ach', 'glyp-payment_application_apply', 'glyp-payment_application_correction', 'glyp-payment_application_initial', 'glyp-payment_application_refund', 'glyp-payment_application_transfer', 'glyp-payment_application_unapply', 'glyp-payment_application_unapply_all', 'glyp-payment_applications', 'glyp-payment_batch', 'glyp-payment_cash', 'glyp-payment_check', 'glyp-payment_coupon', 'glyp-payment_credit', 'glyp-payment_discount', 'glyp-payment_eft', 'glyp-payment_finance_charge', 'glyp-payments', 'glyp-payroll', 'glyp-pdf', 'glyp-pending', 'glyp-periodic', 'glyp-periodic_assessment', 'glyp-permission', 'glyp-pest', 'glyp-pest_ants', 'glyp-pest_bats', 'glyp-pest_bed_bugs', 'glyp-pest_birds', 'glyp-pest_crawling_insects', 'glyp-pest_dermestids', 'glyp-pest_fall_invaders', 'glyp-pest_flying_insects', 'glyp-pest_moles', 'glyp-pest_mosquitoes', 'glyp-pest_nuisance_animals', 'glyp-pest_ornamental', 'glyp-pest_ornamental_diseases', 'glyp-pest_roaches', 'glyp-pest_rodents', 'glyp-pest_scorpions', 'glyp-pest_snakes', 'glyp-pest_spiders', 'glyp-pest_stinging_insects', 'glyp-pest_stored_product_pests', 'glyp-pest_ticks_and_fleas', 'glyp-pest_viruses_and_bacteria', 'glyp-pest_weeds', 'glyp-pest_wood_destroyers', 'glyp-phone', 'glyp-pick_date', 'glyp-pick_list', 'glyp-platform_android', 'glyp-platform_ios', 'glyp-platform_macos', 'glyp-platform_windows', 'glyp-play', 'glyp-plus', 'glyp-plus_filled', 'glyp-portal', 'glyp-price_increase', 'glyp-price_increase_alt', 'glyp-pricing_table', 'glyp-print', 'glyp-privacy', 'glyp-product_sale', 'glyp-production', 'glyp-professional_consultation', 'glyp-program', 'glyp-program_elements', 'glyp-program_initiation', 'glyp-program_order', 'glyp-program_review', 'glyp-promo', 'glyp-proposal', 'glyp-protection', 'glyp-purchase_order', 'glyp-quality', 'glyp-radio_checked', 'glyp-radio_empty', 'glyp-reassign', 'glyp-receipt', 'glyp-recent', 'glyp-recommendation', 'glyp-record_details', 'glyp-recurring_revenue', 'glyp-redo', 'glyp-refresh', 'glyp-refund', 'glyp-region', 'glyp-released', 'glyp-remove', 'glyp-renewal', 'glyp-report', 'glyp-required_input', 'glyp-reschedule', 'glyp-restaurant_bar', 'glyp-revenue', 'glyp-review', 'glyp-rfid', 'glyp-ride_along', 'glyp-rodent_exclusion', 'glyp-route_change', 'glyp-route_optimization', 'glyp-rows', 'glyp-ruler', 'glyp-sales', 'glyp-sales_contest', 'glyp-sales_pipeline', 'glyp-sales_tax', 'glyp-sales_tax_exemption', 'glyp-schedule_lock', 'glyp-schedule_lock_afternoon', 'glyp-schedule_lock_day', 'glyp-schedule_lock_exact', 'glyp-schedule_lock_four_hour', 'glyp-schedule_lock_morning', 'glyp-schedule_lock_none', 'glyp-schedule_lock_two_day', 'glyp-schedule_lock_two_hour', 'glyp-schedule_lock_week', 'glyp-schedule_tyoe_every', 'glyp-schedule_type_every', 'glyp-schedule_type_none', 'glyp-schedule_type_on_demand', 'glyp-schedule_type_schedule', 'glyp-scheduled', 'glyp-scheduling', 'glyp-school_church', 'glyp-script', 'glyp-search', 'glyp-seeding', 'glyp-segment', 'glyp-sent', 'glyp-sentricon', 'glyp-service_agreement', 'glyp-service_form', 'glyp-service_miscellaneous', 'glyp-service_reminder', 'glyp-service_report', 'glyp-service_request', 'glyp-services', 'glyp-settings', 'glyp-setup', 'glyp-signature', 'glyp-simulator', 'glyp-site_map', 'glyp-site_map_annotation', 'glyp-site_map_chemical', 'glyp-site_map_edit_details', 'glyp-site_map_edit_geo', 'glyp-site_map_equipment', 'glyp-site_map_exterior', 'glyp-site_map_foundation', 'glyp-site_map_icon', 'glyp-site_map_interior', 'glyp-site_map_label', 'glyp-site_map_perimeter', 'glyp-site_map_settings_left', 'glyp-site_map_settings_right', 'glyp-site_map_template', 'glyp-skip', 'glyp-smart_traps', 'glyp-sms', 'glyp-snow_removal', 'glyp-sort', 'glyp-special', 'glyp-split', 'glyp-spp_scorecard', 'glyp-square_edge', 'glyp-start_sheet', 'glyp-start_time', 'glyp-statement', 'glyp-states', 'glyp-sticky', 'glyp-stop_time', 'glyp-store_material', 'glyp-store_order', 'glyp-store_order_back_order', 'glyp-store_order_cancelled', 'glyp-store_order_complete', 'glyp-store_order_pending', 'glyp-store_order_pending_return', 'glyp-store_order_pre_order', 'glyp-store_order_returned', 'glyp-stores', 'glyp-styling', 'glyp-subscribe', 'glyp-supplemental', 'glyp-support', 'glyp-sync', 'glyp-table', 'glyp-tablet', 'glyp-tablets', 'glyp-tag_manager', 'glyp-tags', 'glyp-task_runs', 'glyp-tech_pest_sightings', 'glyp-technician', 'glyp-technician_approach', 'glyp-template', 'glyp-termite_fumigation', 'glyp-terrier', 'glyp-territory', 'glyp-text', 'glyp-thermometer', 'glyp-third_party_billing', 'glyp-ticket_type', 'glyp-tickets', 'glyp-tidy', 'glyp-time', 'glyp-time_entry', 'glyp-timeline', 'glyp-toolbox', 'glyp-tqi', 'glyp-tracker', 'glyp-tracking', 'glyp-training_course', 'glyp-treatment_split', 'glyp-trends', 'glyp-trip_charge', 'glyp-ui_type', 'glyp-unchecked', 'glyp-undo', 'glyp-unit_sweep', 'glyp-unit_tag', 'glyp-university', 'glyp-unlocked', 'glyp-unscheduled', 'glyp-update_check_positions', 'glyp-upload', 'glyp-user', 'glyp-user_credit', 'glyp-user_tags', 'glyp-users', 'glyp-utility', 'glyp-vacation', 'glyp-vacuum', 'glyp-variant', 'glyp-vendor', 'glyp-versions', 'glyp-video', 'glyp-visible', 'glyp-warehouse', 'glyp-wdo', 'glyp-web_dusting', 'glyp-website', 'glyp-wildlife', 'glyp-wildlife_exclusion', 'glyp-winter_check', 'glyp-wizard', 'glyp-work', 'glyp-work_class', 'glyp-work_code', 'glyp-work_order', 'glyp-work_production', 'glyp-work_progress', 'glyp-work_yield', 'glyp-year', 'glyp-yield', 'glyp-zip_code', 'glyp-zone_adjacent', 'glyp-zone_check', 'glyp-zone_production', 'glyp-zone_remote', 'glyp-zoom_fit'] as const
3
+ const names = ['glyp-abacus', 'glyp-account', 'glyp-accounts_payable', 'glyp-accounts_receivable', 'glyp-action_log', 'glyp-activate', 'glyp-active', 'glyp-activity_high', 'glyp-activity_low', 'glyp-activity_medium', 'glyp-activity_none', 'glyp-address1', 'glyp-adjustment', 'glyp-admin', 'glyp-administration', 'glyp-air_freshener', 'glyp-alert', 'glyp-align_horizontal', 'glyp-align_vertical', 'glyp-anchor', 'glyp-announcement', 'glyp-app_update', 'glyp-append_selection', 'glyp-appointment', 'glyp-appointment_setup', 'glyp-archive', 'glyp-arrow_down', 'glyp-arrow_left', 'glyp-arrow_right', 'glyp-arrow_transfer', 'glyp-arrow_up', 'glyp-ascending', 'glyp-attachment', 'glyp-audit_analyzer', 'glyp-autopay', 'glyp-availability', 'glyp-background_batch', 'glyp-background_job', 'glyp-bait_for_demolition', 'glyp-bar_chart', 'glyp-barcode', 'glyp-bat_exclusion', 'glyp-bed_bug_fumigation', 'glyp-begin_service', 'glyp-belongs_to', 'glyp-billing', 'glyp-billing_office', 'glyp-billing_terms', 'glyp-billto', 'glyp-bioremediation', 'glyp-bird_exclusion', 'glyp-black_light', 'glyp-branch', 'glyp-branch_bats', 'glyp-branch_birds', 'glyp-branch_general', 'glyp-branch_irrigation', 'glyp-branch_landscape', 'glyp-branch_multi_housing', 'glyp-branch_office', 'glyp-branch_orders', 'glyp-branch_residential', 'glyp-branch_sales', 'glyp-branch_termites', 'glyp-branch_weeds', 'glyp-branch_wildlife', 'glyp-build', 'glyp-calculate', 'glyp-calendar', 'glyp-calendar_branch', 'glyp-calendar_map', 'glyp-calendar_rolling', 'glyp-calendar_share', 'glyp-calendar_snap', 'glyp-california', 'glyp-call', 'glyp-callback', 'glyp-camera', 'glyp-cancellation', 'glyp-cancelled', 'glyp-card_american_express', 'glyp-card_discover', 'glyp-card_mastercard', 'glyp-card_visa', 'glyp-catalog', 'glyp-caught', 'glyp-cert', 'glyp-check_all', 'glyp-check_in', 'glyp-check_in_service', 'glyp-checked', 'glyp-checked_empty', 'glyp-checkmark', 'glyp-checkmark_filled', 'glyp-checkout', 'glyp-chemical', 'glyp-chemical_authorization', 'glyp-chemical_backpack_sprayer', 'glyp-chemical_biological_controls', 'glyp-chemical_disinfectant', 'glyp-chemical_fertilizer', 'glyp-chemical_flying_insect_bait', 'glyp-chemical_fumigants', 'glyp-chemical_insect_aerosol', 'glyp-chemical_insect_bait', 'glyp-chemical_insect_dust', 'glyp-chemical_insect_granules', 'glyp-chemical_insect_spray', 'glyp-chemical_label', 'glyp-chemical_mole_bait', 'glyp-chemical_pest_bird_control', 'glyp-chemical_pheromone_products', 'glyp-chemical_power_sprayer', 'glyp-chemical_rodenticide_block', 'glyp-chemical_rodenticide_non_block', 'glyp-chemical_sds', 'glyp-chemical_tree_products', 'glyp-chemical_weed_control', 'glyp-chemical_wildlife_repellents', 'glyp-chemical_wildlife_toxicants', 'glyp-chevron_down', 'glyp-chevron_left', 'glyp-chevron_right', 'glyp-chevron_up', 'glyp-city', 'glyp-click', 'glyp-client_actions', 'glyp-client_pest_sightings', 'glyp-client_required', 'glyp-close', 'glyp-cloud', 'glyp-clypboard', 'glyp-clypedia', 'glyp-clypmart', 'glyp-code', 'glyp-code_details', 'glyp-collections', 'glyp-columns', 'glyp-comment', 'glyp-comment_filled', 'glyp-commission_origin', 'glyp-commissions', 'glyp-company_setup', 'glyp-compass', 'glyp-complete', 'glyp-complete_certificate', 'glyp-complete_enrollment', 'glyp-condition_appliance_machinery', 'glyp-condition_customer', 'glyp-condition_device', 'glyp-condition_door_window', 'glyp-condition_dumpster', 'glyp-condition_entry_point', 'glyp-condition_evidence', 'glyp-condition_exclusion', 'glyp-condition_exterior', 'glyp-condition_interior', 'glyp-condition_plumbing', 'glyp-condition_prep_storage', 'glyp-condition_rodent_evidence', 'glyp-condition_rodent_exclusion', 'glyp-condition_roof_ceiling', 'glyp-condition_structure', 'glyp-condition_supplies', 'glyp-condition_termites', 'glyp-condition_ventilation', 'glyp-condition_wall_floor', 'glyp-condition_wildlife', 'glyp-conditions', 'glyp-consolidate', 'glyp-construction', 'glyp-contract', 'glyp-contract_cancellation', 'glyp-contract_overview', 'glyp-conversation', 'glyp-copesan', 'glyp-copy', 'glyp-credit_memo', 'glyp-credit_non_revenue', 'glyp-credit_production', 'glyp-credit_prospect', 'glyp-credit_sales_bonus', 'glyp-crew', 'glyp-cumulative', 'glyp-cursor', 'glyp-custom_form', 'glyp-customer', 'glyp-customer_service', 'glyp-dashboard', 'glyp-database', 'glyp-dead_animal_removal', 'glyp-default', 'glyp-delete', 'glyp-demo_mode', 'glyp-descending', 'glyp-design', 'glyp-desktop', 'glyp-detail_report', 'glyp-developer', 'glyp-device', 'glyp-device_sync', 'glyp-differential', 'glyp-disable', 'glyp-disabled_filled', 'glyp-distribute_horizontal', 'glyp-distribute_vertical', 'glyp-division', 'glyp-document', 'glyp-documentation', 'glyp-documents', 'glyp-download', 'glyp-driving', 'glyp-duplicate', 'glyp-duplicate_location', 'glyp-duration', 'glyp-edit', 'glyp-email', 'glyp-employment', 'glyp-entertainment_public_venues', 'glyp-equipment_bear_trap', 'glyp-equipment_flying_insect_bait_station', 'glyp-equipment_flying_insect_light_trap', 'glyp-equipment_insect_monitor', 'glyp-equipment_lethal_animal_trap', 'glyp-equipment_live_animal_trap', 'glyp-equipment_live_rodent_trap', 'glyp-equipment_maintenance', 'glyp-equipment_map_viewer', 'glyp-equipment_maps', 'glyp-equipment_mosquito_trap', 'glyp-equipment_other', 'glyp-equipment_pheromone_trap', 'glyp-equipment_pick_up', 'glyp-equipment_rodent_bait', 'glyp-equipment_rodent_trap', 'glyp-equipment_termite_bait_station', 'glyp-equipment_termite_monitor', 'glyp-exclusion', 'glyp-expand', 'glyp-expiring', 'glyp-exterior', 'glyp-extras', 'glyp-facebook', 'glyp-farm', 'glyp-farm_grain_seed', 'glyp-fast_and_frequent', 'glyp-favorite', 'glyp-feedback', 'glyp-field_guide', 'glyp-field_training', 'glyp-file_blank', 'glyp-file_html', 'glyp-file_image', 'glyp-file_pdf', 'glyp-file_printable', 'glyp-file_spreadsheet', 'glyp-file_text', 'glyp-filter', 'glyp-finance', 'glyp-finding', 'glyp-folder', 'glyp-followup', 'glyp-food_bev_pharma', 'glyp-formula', 'glyp-fuel', 'glyp-fumigation', 'glyp-gain_loss', 'glyp-generate_invoices', 'glyp-generate_orders', 'glyp-geo', 'glyp-geo_heat_map', 'glyp-google', 'glyp-google_calendar', 'glyp-government', 'glyp-grain_seed', 'glyp-grid', 'glyp-grouping_combine', 'glyp-grouping_separate', 'glyp-has_many', 'glyp-health_care', 'glyp-heat_map', 'glyp-heat_treatment', 'glyp-help', 'glyp-hidden', 'glyp-honeybee_removal', 'glyp-housing', 'glyp-in_progress', 'glyp-incomplete_certificate', 'glyp-industrial', 'glyp-info', 'glyp-information_technology', 'glyp-inspect_map', 'glyp-inspections', 'glyp-insulation', 'glyp-interior', 'glyp-invoice', 'glyp-invoice_review', 'glyp-irrigation_install', 'glyp-irrigation_maintenance', 'glyp-items', 'glyp-job', 'glyp-join', 'glyp-join_inner', 'glyp-join_left', 'glyp-justice', 'glyp-k9_inspection', 'glyp-key', 'glyp-label_bottom', 'glyp-label_left', 'glyp-label_right', 'glyp-label_top', 'glyp-labor', 'glyp-landscape', 'glyp-landscape_maintenance', 'glyp-laptop', 'glyp-lead', 'glyp-lead_listing', 'glyp-lead_source', 'glyp-leads_report', 'glyp-learning_hub', 'glyp-ledger', 'glyp-legal', 'glyp-license', 'glyp-lifetime', 'glyp-line_cap_arrow', 'glyp-line_cap_bar', 'glyp-line_cap_circle', 'glyp-line_cap_none', 'glyp-line_caps', 'glyp-line_style', 'glyp-link', 'glyp-location', 'glyp-location_charge', 'glyp-location_credit', 'glyp-location_kind', 'glyp-location_message', 'glyp-location_origin', 'glyp-location_tags', 'glyp-locations', 'glyp-locked', 'glyp-lodging', 'glyp-log_in', 'glyp-log_out', 'glyp-log_report', 'glyp-logbook', 'glyp-logbook_documents', 'glyp-lot_number', 'glyp-manager', 'glyp-map', 'glyp-markdown', 'glyp-market', 'glyp-materials', 'glyp-mattress_encasement', 'glyp-merge', 'glyp-message_billing', 'glyp-message_collections', 'glyp-message_complaint', 'glyp-message_misc', 'glyp-message_technician', 'glyp-messages', 'glyp-misc', 'glyp-miscellaneous', 'glyp-move_order', 'glyp-mowing', 'glyp-multi_housing', 'glyp-mute', 'glyp-navicon', 'glyp-new_location', 'glyp-no_charge', 'glyp-no_service', 'glyp-note', 'glyp-note_access', 'glyp-note_billing', 'glyp-note_collection', 'glyp-note_complaint', 'glyp-note_directions', 'glyp-note_focused', 'glyp-note_office', 'glyp-note_preservice', 'glyp-note_sales', 'glyp-note_service', 'glyp-notification', 'glyp-number', 'glyp-office', 'glyp-office_government', 'glyp-office_training', 'glyp-on_demand', 'glyp-on_demand_order', 'glyp-open', 'glyp-open_invoice', 'glyp-operations', 'glyp-options', 'glyp-order_actions', 'glyp-order_approved', 'glyp-order_batch', 'glyp-order_editor', 'glyp-order_pending', 'glyp-order_series', 'glyp-order_unapproved', 'glyp-org_structure', 'glyp-org_unit', 'glyp-org_unit_settings', 'glyp-origin', 'glyp-origin_client', 'glyp-origin_tech', 'glyp-outlook', 'glyp-overlap', 'glyp-password', 'glyp-past_due', 'glyp-paused', 'glyp-pay_brackets', 'glyp-payment', 'glyp-payment_ach', 'glyp-payment_application_apply', 'glyp-payment_application_correction', 'glyp-payment_application_initial', 'glyp-payment_application_refund', 'glyp-payment_application_transfer', 'glyp-payment_application_unapply', 'glyp-payment_application_unapply_all', 'glyp-payment_applications', 'glyp-payment_batch', 'glyp-payment_cash', 'glyp-payment_check', 'glyp-payment_coupon', 'glyp-payment_credit', 'glyp-payment_discount', 'glyp-payment_eft', 'glyp-payment_finance_charge', 'glyp-payments', 'glyp-payroll', 'glyp-pdf', 'glyp-pending', 'glyp-periodic', 'glyp-periodic_assessment', 'glyp-permission', 'glyp-pest', 'glyp-pest_ants', 'glyp-pest_bats', 'glyp-pest_bed_bugs', 'glyp-pest_birds', 'glyp-pest_crawling_insects', 'glyp-pest_dermestids', 'glyp-pest_fall_invaders', 'glyp-pest_flying_insects', 'glyp-pest_moles', 'glyp-pest_mosquitoes', 'glyp-pest_nuisance_animals', 'glyp-pest_ornamental', 'glyp-pest_ornamental_diseases', 'glyp-pest_roaches', 'glyp-pest_rodents', 'glyp-pest_scorpions', 'glyp-pest_snakes', 'glyp-pest_spiders', 'glyp-pest_stinging_insects', 'glyp-pest_stored_product_pests', 'glyp-pest_ticks_and_fleas', 'glyp-pest_viruses_and_bacteria', 'glyp-pest_weeds', 'glyp-pest_wood_destroyers', 'glyp-phone', 'glyp-pick_date', 'glyp-pick_list', 'glyp-platform_android', 'glyp-platform_ios', 'glyp-platform_macos', 'glyp-platform_windows', 'glyp-play', 'glyp-plus', 'glyp-plus_filled', 'glyp-portal', 'glyp-price_increase', 'glyp-price_increase_alt', 'glyp-pricing_table', 'glyp-print', 'glyp-privacy', 'glyp-product_sale', 'glyp-production', 'glyp-professional_consultation', 'glyp-program', 'glyp-program_elements', 'glyp-program_initiation', 'glyp-program_order', 'glyp-program_review', 'glyp-promo', 'glyp-proposal', 'glyp-protection', 'glyp-purchase_order', 'glyp-quality', 'glyp-radio_checked', 'glyp-radio_empty', 'glyp-reassign', 'glyp-receipt', 'glyp-recent', 'glyp-recommendation', 'glyp-record_details', 'glyp-recurring_revenue', 'glyp-redo', 'glyp-refresh', 'glyp-refund', 'glyp-region', 'glyp-released', 'glyp-remove', 'glyp-renewal', 'glyp-report', 'glyp-required_input', 'glyp-reschedule', 'glyp-restaurant_bar', 'glyp-revenue', 'glyp-review', 'glyp-rfid', 'glyp-ride_along', 'glyp-rodent_exclusion', 'glyp-route_change', 'glyp-route_optimization', 'glyp-rows', 'glyp-ruler', 'glyp-sales', 'glyp-sales_contest', 'glyp-sales_pipeline', 'glyp-sales_tax', 'glyp-sales_tax_exemption', 'glyp-schedule_lock', 'glyp-schedule_lock_afternoon', 'glyp-schedule_lock_day', 'glyp-schedule_lock_exact', 'glyp-schedule_lock_four_hour', 'glyp-schedule_lock_morning', 'glyp-schedule_lock_none', 'glyp-schedule_lock_two_day', 'glyp-schedule_lock_two_hour', 'glyp-schedule_lock_week', 'glyp-schedule_tyoe_every', 'glyp-schedule_type_every', 'glyp-schedule_type_none', 'glyp-schedule_type_on_demand', 'glyp-schedule_type_schedule', 'glyp-scheduled', 'glyp-scheduling', 'glyp-school_church', 'glyp-script', 'glyp-search', 'glyp-seeding', 'glyp-segment', 'glyp-sent', 'glyp-sentricon', 'glyp-service_agreement', 'glyp-service_form', 'glyp-service_miscellaneous', 'glyp-service_reminder', 'glyp-service_report', 'glyp-service_request', 'glyp-services', 'glyp-settings', 'glyp-setup', 'glyp-signature', 'glyp-simulator', 'glyp-site_map', 'glyp-site_map_annotation', 'glyp-site_map_chemical', 'glyp-site_map_edit_details', 'glyp-site_map_edit_geo', 'glyp-site_map_equipment', 'glyp-site_map_exterior', 'glyp-site_map_foundation', 'glyp-site_map_icon', 'glyp-site_map_interior', 'glyp-site_map_label', 'glyp-site_map_perimeter', 'glyp-site_map_settings_left', 'glyp-site_map_settings_right', 'glyp-site_map_template', 'glyp-skip', 'glyp-smart_traps', 'glyp-sms', 'glyp-snow_removal', 'glyp-sort', 'glyp-special', 'glyp-split', 'glyp-spp_scorecard', 'glyp-square_edge', 'glyp-start_sheet', 'glyp-start_time', 'glyp-statement', 'glyp-states', 'glyp-sticky', 'glyp-stop_time', 'glyp-store_material', 'glyp-store_order', 'glyp-store_order_back_order', 'glyp-store_order_cancelled', 'glyp-store_order_complete', 'glyp-store_order_pending', 'glyp-store_order_pending_return', 'glyp-store_order_pre_order', 'glyp-store_order_returned', 'glyp-stores', 'glyp-styling', 'glyp-subscribe', 'glyp-supplemental', 'glyp-support', 'glyp-sync', 'glyp-table', 'glyp-tablet', 'glyp-tablets', 'glyp-tag_manager', 'glyp-tags', 'glyp-task_runs', 'glyp-tech_pest_sightings', 'glyp-technician', 'glyp-technician_approach', 'glyp-template', 'glyp-termite_fumigation', 'glyp-terrier', 'glyp-territory', 'glyp-text', 'glyp-thermometer', 'glyp-third_party_billing', 'glyp-ticket_type', 'glyp-tickets', 'glyp-tidy', 'glyp-time', 'glyp-time_entry', 'glyp-timeline', 'glyp-toolbox', 'glyp-tqi', 'glyp-tracker', 'glyp-tracking', 'glyp-training_course', 'glyp-treatment_split', 'glyp-trends', 'glyp-trip_charge', 'glyp-ui_type', 'glyp-unchecked', 'glyp-undo', 'glyp-unit_sweep', 'glyp-unit_tag', 'glyp-university', 'glyp-unlocked', 'glyp-unscheduled', 'glyp-update_check_positions', 'glyp-upload', 'glyp-user', 'glyp-user_credit', 'glyp-user_tags', 'glyp-users', 'glyp-utility', 'glyp-vacation', 'glyp-vacuum', 'glyp-variant', 'glyp-vendor', 'glyp-versions', 'glyp-video', 'glyp-visible', 'glyp-warehouse', 'glyp-wdo', 'glyp-web_dusting', 'glyp-website', 'glyp-wildlife', 'glyp-wildlife_exclusion', 'glyp-winter_check', 'glyp-wizard', 'glyp-work', 'glyp-work_class', 'glyp-work_code', 'glyp-work_order', 'glyp-work_production', 'glyp-work_progress', 'glyp-work_yield', 'glyp-year', 'glyp-yield', 'glyp-zip_code', 'glyp-zone_adjacent', 'glyp-zone_check', 'glyp-zone_production', 'glyp-zone_remote', 'glyp-zoom_fit'] as const
4
4
 
5
5
  const Glyps = {
6
6
  names
package/lightbox.ts CHANGED
@@ -2,7 +2,7 @@ import { Logger } from "tuff-core/logging"
2
2
  import { untypedKey } from "tuff-core/messages"
3
3
  import {Part, PartTag} from "tuff-core/parts"
4
4
  import {TerrierApp} from "./app"
5
- import Theme, {ThemeType} from "./theme";
5
+ import Theme, {ThemeType} from "./theme"
6
6
 
7
7
  const log = new Logger('Lightbox')
8
8
 
@@ -58,7 +58,7 @@ function showPart<
58
58
  TApp extends TerrierApp<TT,TApp, TTheme>,
59
59
  TTheme extends Theme<TT>
60
60
  >(app: TApp, state: LightboxState) {
61
- app.makeOverlay(LightboxPart, {app,...state}, 'lightbox')
61
+ app.addOverlay(LightboxPart, {app,...state}, 'lightbox')
62
62
  }
63
63
 
64
64
  const closeKey = untypedKey()
@@ -91,7 +91,7 @@ class LightboxPart<
91
91
  close() {
92
92
  this.element?.classList.remove('active')
93
93
  setTimeout(_ => {
94
- this.state.app.clearOverlay('lightbox')
94
+ this.state.app.removeOverlay(this.state)
95
95
  }, 500)
96
96
  }
97
97
  }
package/modals.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { Logger } from "tuff-core/logging"
2
2
  import { untypedKey } from "tuff-core/messages"
3
- import {ContentPart, TerrierPart} from "./parts"
3
+ import TerrierPart from "./parts/terrier-part"
4
4
  import {PartConstructor, PartTag} from "tuff-core/parts"
5
- import Theme, {ThemeType} from "./theme";
6
- import {TerrierApp} from "./app";
5
+ import Theme, {ThemeType} from "./theme"
6
+ import {TerrierApp} from "./app"
7
+ import ContentPart from "./parts/content-part"
7
8
 
8
9
  const log = new Logger('Modals')
9
10
 
package/overlays.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { Part, PartParent, PartTag, StatelessPart, NoState } from "tuff-core/parts"
1
+ import {Part, PartTag, StatelessPart, NoState, PartConstructor} from "tuff-core/parts"
2
2
  import { Size, Box, Side } from "tuff-core/box"
3
3
  import { Logger } from "tuff-core/logging"
4
+ import {arrays} from "tuff-core";
4
5
 
5
6
  const log = new Logger('Overlays')
6
7
 
@@ -8,67 +9,133 @@ const log = new Logger('Overlays')
8
9
  // Part
9
10
  ////////////////////////////////////////////////////////////////////////////////
10
11
 
11
- const OverlayLayers = ['modal', 'dropdown', 'lightbox', 'jump'] as const
12
+ const OverlayLayerTypes = ['modal', 'dropdown', 'lightbox', 'jump'] as const
12
13
 
13
14
  /**
14
- * Which overlay layer to use for an overlay part.
15
- * There can only be one part per layer.
15
+ * The type of overlay for any given layer.
16
16
  */
17
- export type OverlayLayer = typeof OverlayLayers[number]
17
+ export type OverlayLayerType = typeof OverlayLayerTypes[number]
18
18
 
19
19
  export class OverlayPart extends Part<NoState> {
20
20
 
21
- parts: {[layer in OverlayLayer]?: StatelessPart} = {}
21
+ layerStates: OverlayLayerState<any, any>[] = []
22
+
23
+ updateLayers(): StatelessPart[] {
24
+ return this.assignCollection('layers', OverlayLayer, this.layerStates)
25
+ }
22
26
 
23
27
  /**
24
- * Creates a part at the given layer.
25
- * Discards the old part at that layer, if there was one.
28
+ * Creates a part and pushes it onto the overlay stack.
26
29
  * @param constructor
27
30
  * @param state
28
- * @param layer
31
+ * @param type
32
+ * @return the new part
29
33
  */
30
- makeLayer<PartType extends Part<StateType>, StateType>(
31
- constructor: { new(p: PartParent, id: string, state: StateType): PartType; },
34
+ pushLayer<PartType extends Part<StateType>, StateType extends {}>(
35
+ constructor: PartConstructor<PartType, StateType>,
32
36
  state: StateType,
33
- layer: OverlayLayer
37
+ type: OverlayLayerType
34
38
  ): PartType {
35
- const part = this.makePart(constructor, state)
36
- this.clearLayer(layer)
37
- this.parts[layer] = part
38
- return part
39
+ this.layerStates.push({partClass: constructor, partState: state, type})
40
+ const parts = this.updateLayers()
41
+ return (parts[parts.length-1] as OverlayLayer<PartType, StateType>).part as PartType
39
42
  }
40
43
 
41
44
  /**
42
- * Clear a single overlay layer.
43
- * @param layer
45
+ * Same as `pushLayer`, except that it will re-use the first existing layer of the given type, if present.
46
+ * @param constructor
47
+ * @param state
48
+ * @param type
49
+ * @return the new or existing part
44
50
  */
45
- clearLayer(layer: OverlayLayer) {
46
- const layerPart = this.parts[layer]
47
- if (layerPart) {
48
- this.removeChild(layerPart)
49
- this.parts[layer] = undefined
51
+ getOrCreateLayer<PartType extends Part<StateType>, StateType extends {}>(
52
+ constructor: PartConstructor<PartType, StateType>,
53
+ state: StateType,
54
+ type: OverlayLayerType
55
+ ): PartType {
56
+ const layers = this.getCollectionParts('layers')
57
+ for (const layer of layers) {
58
+ if (layer.state.type == type) {
59
+ return (layer as OverlayLayer<PartType, StateType>).part as PartType
60
+ }
50
61
  }
51
- this.dirty()
62
+ const part = this.pushLayer(constructor, state, type)
63
+ return part as PartType
52
64
  }
53
65
 
54
66
  /**
55
- * Clear all overlay layers.
67
+ * Pops the top layer off the overlay stack.
68
+ * @return the part that was popped, if there was one.
56
69
  */
57
- clearAll() {
58
- for (const layer of OverlayLayers) {
59
- this.clearLayer(layer)
70
+ popLayer(type?: OverlayLayerType): StatelessPart | undefined {
71
+ const oldParts = this.getCollectionParts('layers')
72
+ if (type) {
73
+ for (let i = this.layerStates.length-1; i>=0; i--) {
74
+ if (this.layerStates[i].type == type) {
75
+ const part = oldParts[i]
76
+ this.layerStates = arrays.without(this.layerStates, this.layerStates[i])
77
+ this.updateLayers()
78
+ return part
79
+ }
80
+ }
81
+ return undefined
82
+ }
83
+ else {
84
+ // no type specified, pop the top one
85
+ this.layerStates = this.layerStates.slice(0, this.layerStates.length - 1)
86
+ this.updateLayers()
87
+ return oldParts[oldParts.length - 1]
60
88
  }
61
89
  }
62
90
 
63
- render(parent: PartTag) {
64
- for (const layer of OverlayLayers) {
65
- const part = this.parts[layer]
66
- if (part) {
67
- parent.div(layer).part(part)
91
+ /**
92
+ * Removes the layer with the given state from the stack.
93
+ * @param state
94
+ * @return true if there was a layer actually removed
95
+ */
96
+ removeLayer<StateType extends {}>(state: StateType): boolean {
97
+ for (const layerState of this.layerStates) {
98
+ if (layerState.partState == state) {
99
+ this.layerStates = arrays.without(this.layerStates, layerState)
100
+ this.updateLayers()
101
+ return true
68
102
  }
69
103
  }
104
+ return false
105
+ }
106
+
107
+ /**
108
+ * Clear all overlay layers.
109
+ */
110
+ clearAll() {
111
+ this.layerStates = []
112
+ }
113
+
114
+ render(parent: PartTag) {
115
+ this.renderCollection(parent, 'layers')
116
+ }
117
+
118
+ }
119
+
120
+ type OverlayLayerState<PartType extends Part<StateType>, StateType extends {}> = {
121
+ partClass: PartConstructor<PartType, StateType>
122
+ partState: StateType
123
+ type: OverlayLayerType
124
+ }
125
+
126
+ class OverlayLayer<PartType extends Part<StateType>, StateType extends {}> extends Part<OverlayLayerState<PartType, StateType>> {
127
+
128
+ part!: PartType
129
+
130
+ async init() {
131
+ this.part = this.makePart(this.state.partClass, this.state.partState)
70
132
  }
71
133
 
134
+ render(parent: PartTag) {
135
+ parent.part(this.part)
136
+ }
137
+
138
+
72
139
  }
73
140
 
74
141
 
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "files": [
5
5
  "*"
6
6
  ],
7
- "version": "4.0.21",
7
+ "version": "4.1.0",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Terrier-Tech/terrier-engine"