From b70aa2c45f03b3b03d4b81566193a70c17c61d4c Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 8 Jul 2025 08:10:17 -0700 Subject: [PATCH] refactor: circular deps part 5 --- .../accessibility/accessibility-css-helper.ts | 127 +----------------- .../accessibility/accessibility-css-init.ts | 121 +++++++++++++++++ .../accessibility/accessibility-properties.ts | 2 +- .../core/application/application-common.ts | 2 +- packages/core/ui/core/view-base/index.ts | 14 +- packages/core/ui/core/view-base/utils.ts | 9 ++ 6 files changed, 138 insertions(+), 137 deletions(-) create mode 100644 packages/core/accessibility/accessibility-css-init.ts create mode 100644 packages/core/ui/core/view-base/utils.ts diff --git a/packages/core/accessibility/accessibility-css-helper.ts b/packages/core/accessibility/accessibility-css-helper.ts index ec1790614..2244b86af 100644 --- a/packages/core/accessibility/accessibility-css-helper.ts +++ b/packages/core/accessibility/accessibility-css-helper.ts @@ -1,125 +1,4 @@ -import { Application } from '../application'; -import type { View } from '../ui/core/view'; -import { AccessibilityServiceEnabledObservable } from './accessibility-service'; -import { FontScaleCategory, getCurrentFontScale, getFontScaleCategory, VALID_FONT_SCALES } from './font-scale'; +// Only keep helpers that do not import from application here. +// If any code remains that needs Application, move it to accessibility-css-init.ts. -// CSS-classes -const fontScaleExtraSmallCategoryClass = `a11y-fontscale-xs`; -const fontScaleMediumCategoryClass = `a11y-fontscale-m`; -const fontScaleExtraLargeCategoryClass = `a11y-fontscale-xl`; - -const fontScaleCategoryClasses = [fontScaleExtraSmallCategoryClass, fontScaleMediumCategoryClass, fontScaleExtraLargeCategoryClass]; - -const a11yServiceEnabledClass = `a11y-service-enabled`; -const a11yServiceDisabledClass = `a11y-service-disabled`; -const a11yServiceClasses = [a11yServiceEnabledClass, a11yServiceDisabledClass]; - -let accessibilityServiceObservable: AccessibilityServiceEnabledObservable; -let fontScaleCssClasses: Map; - -let currentFontScaleClass = ''; -let currentFontScaleCategory = ''; -let currentA11YServiceClass = ''; - -function ensureClasses() { - if (accessibilityServiceObservable) { - return; - } - - fontScaleCssClasses = new Map(VALID_FONT_SCALES.map((fs) => [fs, `a11y-fontscale-${Number(fs * 100).toFixed(0)}`])); - - accessibilityServiceObservable = new AccessibilityServiceEnabledObservable(); -} - -function applyRootCssClass(cssClasses: string[], newCssClass: string): void { - const rootView = Application.getRootView(); - if (!rootView) { - return; - } - - Application.applyCssClass(rootView, cssClasses, newCssClass); - - const rootModalViews = >rootView._getRootModalViews(); - rootModalViews.forEach((rootModalView) => Application.applyCssClass(rootModalView, cssClasses, newCssClass)); -} - -function applyFontScaleToRootViews(): void { - const rootView = Application.getRootView(); - if (!rootView) { - return; - } - - const fontScale = getCurrentFontScale(); - - rootView.style.fontScaleInternal = fontScale; - - const rootModalViews = >rootView._getRootModalViews(); - rootModalViews.forEach((rootModalView) => (rootModalView.style.fontScaleInternal = fontScale)); -} - -export function initAccessibilityCssHelper(): void { - ensureClasses(); - - Application.on(Application.fontScaleChangedEvent, () => { - updateCurrentHelperClasses(); - - applyFontScaleToRootViews(); - }); - - accessibilityServiceObservable.on(AccessibilityServiceEnabledObservable.propertyChangeEvent, updateCurrentHelperClasses); -} - -/** - * Update the helper CSS-classes. - * Return true is any changes. - */ -function updateCurrentHelperClasses(): void { - const fontScale = getCurrentFontScale(); - const fontScaleCategory = getFontScaleCategory(); - - const oldFontScaleClass = currentFontScaleClass; - if (fontScaleCssClasses.has(fontScale)) { - currentFontScaleClass = fontScaleCssClasses.get(fontScale); - } else { - currentFontScaleClass = fontScaleCssClasses.get(1); - } - - if (oldFontScaleClass !== currentFontScaleClass) { - applyRootCssClass([...fontScaleCssClasses.values()], currentFontScaleClass); - } - - const oldActiveFontScaleCategory = currentFontScaleCategory; - switch (fontScaleCategory) { - case FontScaleCategory.ExtraSmall: { - currentFontScaleCategory = fontScaleExtraSmallCategoryClass; - break; - } - case FontScaleCategory.Medium: { - currentFontScaleCategory = fontScaleMediumCategoryClass; - break; - } - case FontScaleCategory.ExtraLarge: { - currentFontScaleCategory = fontScaleExtraLargeCategoryClass; - break; - } - default: { - currentFontScaleCategory = fontScaleMediumCategoryClass; - break; - } - } - - if (oldActiveFontScaleCategory !== currentFontScaleCategory) { - applyRootCssClass(fontScaleCategoryClasses, currentFontScaleCategory); - } - - const oldA11YStatusClass = currentA11YServiceClass; - if (accessibilityServiceObservable.accessibilityServiceEnabled) { - currentA11YServiceClass = a11yServiceEnabledClass; - } else { - currentA11YServiceClass = a11yServiceDisabledClass; - } - - if (oldA11YStatusClass !== currentA11YServiceClass) { - applyRootCssClass(a11yServiceClasses, currentA11YServiceClass); - } -} +export { initAccessibilityCssHelper } from './accessibility-css-init'; diff --git a/packages/core/accessibility/accessibility-css-init.ts b/packages/core/accessibility/accessibility-css-init.ts new file mode 100644 index 000000000..1d3851969 --- /dev/null +++ b/packages/core/accessibility/accessibility-css-init.ts @@ -0,0 +1,121 @@ +import { Application } from '../application'; +import type { View } from '../ui/core/view'; +import { AccessibilityServiceEnabledObservable } from './accessibility-service'; +import { FontScaleCategory, getCurrentFontScale, getFontScaleCategory, VALID_FONT_SCALES } from './font-scale'; + +// CSS-classes +const fontScaleExtraSmallCategoryClass = `a11y-fontscale-xs`; +const fontScaleMediumCategoryClass = `a11y-fontscale-m`; +const fontScaleExtraLargeCategoryClass = `a11y-fontscale-xl`; + +const fontScaleCategoryClasses = [fontScaleExtraSmallCategoryClass, fontScaleMediumCategoryClass, fontScaleExtraLargeCategoryClass]; + +const a11yServiceEnabledClass = `a11y-service-enabled`; +const a11yServiceDisabledClass = `a11y-service-disabled`; +const a11yServiceClasses = [a11yServiceEnabledClass, a11yServiceDisabledClass]; + +let accessibilityServiceObservable: AccessibilityServiceEnabledObservable; +let fontScaleCssClasses: Map; + +let currentFontScaleClass = ''; +let currentFontScaleCategory = ''; +let currentA11YServiceClass = ''; + +function ensureClasses() { + if (accessibilityServiceObservable) { + return; + } + + fontScaleCssClasses = new Map(VALID_FONT_SCALES.map((fs) => [fs, `a11y-fontscale-${Number(fs * 100).toFixed(0)}`])); + + accessibilityServiceObservable = new AccessibilityServiceEnabledObservable(); +} + +function applyRootCssClass(cssClasses: string[], newCssClass: string): void { + const rootView = Application.getRootView(); + if (!rootView) { + return; + } + + Application.applyCssClass(rootView, cssClasses, newCssClass); + + const rootModalViews = >rootView._getRootModalViews(); + rootModalViews.forEach((rootModalView) => Application.applyCssClass(rootModalView, cssClasses, newCssClass)); +} + +function applyFontScaleToRootViews(): void { + const rootView = Application.getRootView(); + if (!rootView) { + return; + } + + const fontScale = getCurrentFontScale(); + + rootView.style.fontScaleInternal = fontScale; + + const rootModalViews = >rootView._getRootModalViews(); + rootModalViews.forEach((rootModalView) => (rootModalView.style.fontScaleInternal = fontScale)); +} + +function updateCurrentHelperClasses(): void { + const fontScale = getCurrentFontScale(); + const fontScaleCategory = getFontScaleCategory(); + + const oldFontScaleClass = currentFontScaleClass; + if (fontScaleCssClasses.has(fontScale)) { + currentFontScaleClass = fontScaleCssClasses.get(fontScale); + } else { + currentFontScaleClass = fontScaleCssClasses.get(1); + } + + if (oldFontScaleClass !== currentFontScaleClass) { + applyRootCssClass([...fontScaleCssClasses.values()], currentFontScaleClass); + } + + const oldActiveFontScaleCategory = currentFontScaleCategory; + switch (fontScaleCategory) { + case FontScaleCategory.ExtraSmall: { + currentFontScaleCategory = fontScaleExtraSmallCategoryClass; + break; + } + case FontScaleCategory.Medium: { + currentFontScaleCategory = fontScaleMediumCategoryClass; + break; + } + case FontScaleCategory.ExtraLarge: { + currentFontScaleCategory = fontScaleExtraLargeCategoryClass; + break; + } + default: { + currentFontScaleCategory = fontScaleMediumCategoryClass; + break; + } + } + + if (oldActiveFontScaleCategory !== currentFontScaleCategory) { + applyRootCssClass(fontScaleCategoryClasses, currentFontScaleCategory); + } + + const oldA11YStatusClass = currentA11YServiceClass; + if (accessibilityServiceObservable.accessibilityServiceEnabled) { + currentA11YServiceClass = a11yServiceEnabledClass; + } else { + currentA11YServiceClass = a11yServiceDisabledClass; + } + + if (oldA11YStatusClass !== currentA11YServiceClass) { + applyRootCssClass(a11yServiceClasses, currentA11YServiceClass); + } +} + +export function initAccessibilityCssHelper(): void { + ensureClasses(); + + Application.on(Application.fontScaleChangedEvent, () => { + updateCurrentHelperClasses(); + + applyFontScaleToRootViews(); + }); + + accessibilityServiceObservable.on(AccessibilityServiceEnabledObservable.propertyChangeEvent, updateCurrentHelperClasses); +} diff --git a/packages/core/accessibility/accessibility-properties.ts b/packages/core/accessibility/accessibility-properties.ts index 96d99df74..ade765a5d 100644 --- a/packages/core/accessibility/accessibility-properties.ts +++ b/packages/core/accessibility/accessibility-properties.ts @@ -1,6 +1,6 @@ import { CssProperty, InheritedCssProperty, Property } from '../ui/core/properties'; import type { View } from '../ui/core/view'; -import { booleanConverter } from '../ui/core/view-base'; +import { booleanConverter } from '../ui/core/view-base/utils'; import { Style } from '../ui/styling/style'; import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait } from './accessibility-types'; diff --git a/packages/core/application/application-common.ts b/packages/core/application/application-common.ts index 301c1adc4..33c58defd 100644 --- a/packages/core/application/application-common.ts +++ b/packages/core/application/application-common.ts @@ -1,4 +1,4 @@ -import { initAccessibilityCssHelper } from '../accessibility/accessibility-css-helper'; +import { initAccessibilityCssHelper } from '../accessibility/accessibility-css-init'; import { initAccessibilityFontScale } from '../accessibility/font-scale'; import { CoreTypes } from '../core-types'; import { CSSUtils } from '../css/system-classes'; diff --git a/packages/core/ui/core/view-base/index.ts b/packages/core/ui/core/view-base/index.ts index e7c897416..26d251ba0 100644 --- a/packages/core/ui/core/view-base/index.ts +++ b/packages/core/ui/core/view-base/index.ts @@ -20,6 +20,9 @@ import { profile } from '../../../profiling'; import { DOMNode } from '../../../debugger/dom-types'; import { applyInlineStyle, CssState, StyleScope } from '../../styling/style-scope'; import { ViewBase as ViewBaseDefinition } from '.'; +import { booleanConverter } from './utils'; + +export { booleanConverter } from './utils'; const defaultBindingSource = {}; @@ -1613,14 +1616,3 @@ export const defaultVisualStateProperty = new Property({ }, }); defaultVisualStateProperty.register(ViewBase); - -export function booleanConverter(v: string | boolean): boolean { - const lowercase = (v + '').toLowerCase(); - if (lowercase === 'true') { - return true; - } else if (lowercase === 'false') { - return false; - } - - throw new Error(`Invalid boolean: ${v}`); -} diff --git a/packages/core/ui/core/view-base/utils.ts b/packages/core/ui/core/view-base/utils.ts new file mode 100644 index 000000000..e4fac75d7 --- /dev/null +++ b/packages/core/ui/core/view-base/utils.ts @@ -0,0 +1,9 @@ +// Utility functions for view-base and related modules + +export function booleanConverter(v: string | boolean): boolean { + if (typeof v === 'string') { + v = v.trim().toLowerCase(); + return v === 'true' || v === '1'; + } + return !!v; +}