@onekeyfe/react-native-native-list 6.7.0-alpha.375 → 6.7.0-alpha.382
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/android/src/main/java/com/onekey/nativelist/HybridNativeList.kt +14 -1
- package/android/src/main/java/com/onekey/nativelist/NativeListAccessoryStack.kt +240 -11
- package/android/src/main/java/com/onekey/nativelist/NativeListActivityDetailsView.kt +7 -4
- package/android/src/main/java/com/onekey/nativelist/NativeListActivityRenderer.kt +6 -3
- package/android/src/main/java/com/onekey/nativelist/NativeListButtonGroupRenderer.kt +102 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListContainerSlotAdapter.kt +12 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListDataRowRenderer.kt +87 -7
- package/android/src/main/java/com/onekey/nativelist/NativeListIdentityRenderer.kt +177 -1
- package/android/src/main/java/com/onekey/nativelist/NativeListLeadingVisual.kt +43 -14
- package/android/src/main/java/com/onekey/nativelist/NativeListMessageRenderer.kt +25 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +33 -2
- package/android/src/main/java/com/onekey/nativelist/NativeListPrimitives.kt +22 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRendererRegistry.kt +2 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRendererRowView.kt +2 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListResolvedText.kt +3 -2
- package/android/src/main/java/com/onekey/nativelist/NativeListSectionHeaderRenderer.kt +69 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListTextView.kt +55 -1
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +1912 -107
- package/android/src/test/java/com/margelo/nitro/nativelist/NativeListPressPolicyTest.kt +1 -0
- package/docs/ROW_TEMPLATES.md +60 -9
- package/docs/SPEC.md +450 -5
- package/docs/STYLE_SPEC.md +6 -0
- package/ios/HybridNativeList.swift +21 -2
- package/ios/NativeListAccessoryStack.swift +227 -39
- package/ios/NativeListActivityDetailsView.swift +18 -8
- package/ios/NativeListActivityRenderer.swift +8 -2
- package/ios/NativeListButtonGroupRenderer.swift +89 -0
- package/ios/NativeListDataRowRenderer.swift +155 -27
- package/ios/NativeListDesignAssets.swift +3 -0
- package/ios/NativeListIdentityRenderer.swift +166 -30
- package/ios/NativeListLeadingVisual.swift +49 -14
- package/ios/NativeListMessageRenderer.swift +34 -1
- package/ios/NativeListModels.swift +42 -2
- package/ios/NativeListRendererRegistry.swift +1 -0
- package/ios/NativeListResolvedText.swift +2 -1
- package/ios/NativeListRowHost.swift +14 -0
- package/ios/NativeListSectionHeaderRenderer.swift +88 -0
- package/ios/RNCNativeListView.swift +1013 -55
- package/ios/Resources/NativeListIcons.xcassets/onekey_crypto_coin_outline.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_crypto_coin_outline.imageset/icon.svg +4 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_gas_solid.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_gas_solid.imageset/icon.svg +3 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_refresh_ccw_outline.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_refresh_ccw_outline.imageset/icon.svg +3 -0
- package/ios/tests/NativeListActivityPresentationTests.swift +56 -0
- package/ios/tests/NativeListLifecycleTests.swift +2720 -3
- package/lib/module/NativeList.js +175 -28
- package/lib/module/NativeList.web.js +129 -30
- package/lib/module/index.js +1 -1
- package/lib/module/models.js +1 -0
- package/lib/module/selection.js +1 -1
- package/lib/module/validation.js +421 -8
- package/lib/module/web/NativeListWebEngine.js +507 -19
- package/lib/module/web/templates/ActivityRowRenderer.js +8 -7
- package/lib/module/web/templates/ButtonGroupRowRenderer.js +47 -0
- package/lib/module/web/templates/DataRowRenderer.js +40 -5
- package/lib/module/web/templates/IdentityRowRenderer.js +90 -4
- package/lib/module/web/templates/MessageRowRenderer.js +18 -2
- package/lib/module/web/templates/RowContainerStyle.js +1 -0
- package/lib/module/web/templates/RowRendererRegistry.js +3 -0
- package/lib/module/web/templates/SectionHeaderRowRenderer.js +36 -2
- package/lib/nitrogen/generated/android/c++/JHybridNativeListSpec.cpp +26 -0
- package/lib/nitrogen/generated/android/c++/JHybridNativeListSpec.hpp +4 -0
- package/lib/nitrogen/generated/android/c++/views/JHybridNativeListStateUpdater.cpp +10 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/HybridNativeListSpec.kt +20 -0
- package/lib/nitrogen/generated/ios/c++/HybridNativeListSpecSwift.hpp +14 -0
- package/lib/nitrogen/generated/ios/c++/views/HybridNativeListComponent.mm +12 -0
- package/lib/nitrogen/generated/ios/swift/HybridNativeListSpec.swift +2 -0
- package/lib/nitrogen/generated/ios/swift/HybridNativeListSpec_cxx.swift +43 -0
- package/lib/nitrogen/generated/shared/c++/HybridNativeListSpec.cpp +4 -0
- package/lib/nitrogen/generated/shared/c++/HybridNativeListSpec.hpp +4 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridNativeListComponent.cpp +4 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridNativeListComponent.hpp +6 -0
- package/lib/nitrogen/generated/shared/json/NativeListConfig.json +2 -0
- package/lib/typescript/src/NativeList.d.ts +1 -1
- package/lib/typescript/src/NativeList.nitro.d.ts +2 -0
- package/lib/typescript/src/NativeList.types.d.ts +18 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/models.d.ts +105 -9
- package/lib/typescript/src/validation.d.ts +12 -0
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +32 -0
- package/lib/typescript/src/web/templates/ButtonGroupRowRenderer.d.ts +14 -0
- package/lib/typescript/src/web/templates/IdentityRowRenderer.d.ts +1 -1
- package/lib/typescript/src/web/templates/MessageRowRenderer.d.ts +9 -3
- package/nitrogen/generated/android/c++/JHybridNativeListSpec.cpp +26 -0
- package/nitrogen/generated/android/c++/JHybridNativeListSpec.hpp +4 -0
- package/nitrogen/generated/android/c++/views/JHybridNativeListStateUpdater.cpp +10 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/HybridNativeListSpec.kt +20 -0
- package/nitrogen/generated/ios/c++/HybridNativeListSpecSwift.hpp +14 -0
- package/nitrogen/generated/ios/c++/views/HybridNativeListComponent.mm +12 -0
- package/nitrogen/generated/ios/swift/HybridNativeListSpec.swift +2 -0
- package/nitrogen/generated/ios/swift/HybridNativeListSpec_cxx.swift +43 -0
- package/nitrogen/generated/shared/c++/HybridNativeListSpec.cpp +4 -0
- package/nitrogen/generated/shared/c++/HybridNativeListSpec.hpp +4 -0
- package/nitrogen/generated/shared/c++/views/HybridNativeListComponent.cpp +4 -0
- package/nitrogen/generated/shared/c++/views/HybridNativeListComponent.hpp +6 -0
- package/nitrogen/generated/shared/json/NativeListConfig.json +2 -0
- package/package.json +3 -3
- package/react-native-native-list.podspec +1 -0
- package/src/NativeList.nitro.ts +2 -0
- package/src/NativeList.tsx +313 -44
- package/src/NativeList.types.ts +22 -0
- package/src/NativeList.web.tsx +204 -48
- package/src/index.ts +2 -0
- package/src/models.ts +117 -3
- package/src/selection.ts +1 -0
- package/src/validation.ts +852 -6
- package/src/web/NativeListWebEngine.ts +803 -20
- package/src/web/templates/ActivityRowRenderer.ts +14 -6
- package/src/web/templates/ButtonGroupRowRenderer.ts +58 -0
- package/src/web/templates/DataRowRenderer.ts +93 -20
- package/src/web/templates/IdentityRowRenderer.ts +150 -5
- package/src/web/templates/MessageRowRenderer.ts +23 -7
- package/src/web/templates/RowContainerStyle.ts +2 -0
- package/src/web/templates/RowRendererRegistry.ts +11 -1
- package/src/web/templates/SectionHeaderRowRenderer.ts +47 -4
|
@@ -421,7 +421,7 @@ export const WEB_LIST_CSS = `
|
|
|
421
421
|
.ok-native-list-table-secondary{display:block;min-width:0;overflow:clip}.ok-native-list-table-secondary-track{display:flex;flex-direction:column;transition:transform 100ms ease}.ok-native-list-market-table:focus-within .ok-native-list-table-secondary[data-has-hover="true"]>.ok-native-list-table-secondary-track{transform:translateY(calc(-1 * var(--nl-table-secondary-height)))}@media(hover:hover){.ok-native-list-market-table:hover .ok-native-list-table-secondary[data-has-hover="true"]>.ok-native-list-table-secondary-track{transform:translateY(calc(-1 * var(--nl-table-secondary-height)))}}.ok-native-list-market-table button:focus-visible{outline:2px solid var(--nl-accent);outline-offset:1px}.ok-native-list-market-table button:hover{opacity:.75}.ok-native-list-market-table button:active{opacity:.5}
|
|
422
422
|
|
|
423
423
|
[data-native-list-selector="walletSidebar"] .ok-native-list-title{max-width:100%;min-width:0}
|
|
424
|
-
.ok-native-list-root{--nl-bg:#f7f7f7;--nl-row:#fff;--nl-selected:#eaf2ff;--nl-pressed:#e8e8e8;--nl-subdued:#f9f9f9;--nl-strong:#0000000f;--nl-primary:#111;--nl-secondary:#6b7280;--nl-disabled:#8d8d8d;--nl-icon:#111;--nl-icon-subdued:#8d8d8d;--nl-separator:#e5e7eb;--nl-accent:#2f6bff;--nl-positive:#15803d;--nl-negative:#dc2626;--nl-critical:#feecec;--nl-inverse:#202020;--nl-inverse-text:#fcfcfc;--nl-info:#0d74ce;position:absolute;inset:0;display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden;background:var(--nl-bg);color:var(--nl-primary);font-synthesis:none;font-family:var(--nl-font-regular)}
|
|
424
|
+
.ok-native-list-root{--nl-bg:#f7f7f7;--nl-row:#fff;--nl-selected:#eaf2ff;--nl-pressed:#e8e8e8;--nl-hover:#e8e8e8;--nl-subdued:#f9f9f9;--nl-strong:#0000000f;--nl-primary:#111;--nl-secondary:#6b7280;--nl-disabled:#8d8d8d;--nl-icon:#111;--nl-icon-subdued:#8d8d8d;--nl-separator:#e5e7eb;--nl-accent:#2f6bff;--nl-positive:#15803d;--nl-negative:#dc2626;--nl-critical:#feecec;--nl-inverse:#202020;--nl-inverse-text:#fcfcfc;--nl-info:#0d74ce;position:absolute;inset:0;display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden;background:var(--nl-bg);color:var(--nl-primary);font-synthesis:none;font-family:var(--nl-font-regular)}
|
|
425
425
|
.ok-native-list-viewport-frame{position:relative;flex:1;min-width:0;min-height:0;overflow:hidden}
|
|
426
426
|
.ok-native-list-viewport{position:absolute;inset:0;overflow:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scrollbar-gutter:stable}
|
|
427
427
|
.ok-native-list-content{position:relative;min-width:100%;min-height:100%}
|
|
@@ -432,7 +432,7 @@ export const WEB_LIST_CSS = `
|
|
|
432
432
|
.ok-native-list-item[data-native-list-selected="true"]>.ok-native-list-row{background:var(--nl-selected)}
|
|
433
433
|
.ok-native-list-item[data-native-list-disabled="true"]>.ok-native-list-row{cursor:default}
|
|
434
434
|
.ok-native-list-item[data-native-list-row-press-enabled="true"]>.ok-native-list-row{cursor:pointer}
|
|
435
|
-
.ok-native-list-item[data-native-list-row-press-enabled="true"]:hover>.ok-native-list-row{background:var(--nl-
|
|
435
|
+
.ok-native-list-item[data-native-list-row-press-enabled="true"]:hover>.ok-native-list-row{background:var(--nl-hover)}
|
|
436
436
|
.ok-native-list-item[data-native-list-row-press-enabled="true"]:active>.ok-native-list-row{background:var(--nl-pressed)}
|
|
437
437
|
.ok-native-list-item[data-native-list-row-press-enabled="true"]:not([data-native-list-selected="true"]):hover>.ok-native-list-wallet-row{background:var(--nl-strong)}
|
|
438
438
|
.ok-native-list-item[data-native-list-row-press-enabled="true"]:not([data-native-list-selected="true"]):active>.ok-native-list-wallet-row{background:var(--nl-pressed)}
|
|
@@ -463,16 +463,23 @@ export const WEB_LIST_CSS = `
|
|
|
463
463
|
.ok-native-list-item[data-group-position="last"]>.ok-native-list-row{border-radius:0 0 var(--nl-group-radius,12px) var(--nl-group-radius,12px)}
|
|
464
464
|
.ok-native-list-item[data-group-position="single"]>.ok-native-list-row{border-radius:var(--nl-group-radius,12px)}
|
|
465
465
|
.ok-native-list-standard{padding:8px 12px}.ok-native-list-network-row{padding:0 12px}.ok-native-list-wallet-row{padding:4px 8px;flex-direction:column;justify-content:center;gap:4px}.ok-native-list-account-row{padding:4px 12px;gap:8px}
|
|
466
|
+
.ok-native-list-trailing-button{appearance:none;box-sizing:border-box;flex:0 0 auto;padding:4px 10px;border:1px solid transparent;border-radius:9999px;background:var(--nl-button-bg,var(--nl-strong));color:var(--nl-button-text,var(--nl-primary));font:500 14px/20px var(--nl-font-medium);white-space:nowrap;cursor:pointer}.ok-native-list-trailing-button:hover:not(:disabled){background:var(--nl-button-hover,var(--nl-strong))}.ok-native-list-trailing-button:active:not(:disabled){background:var(--nl-button-pressed,var(--nl-pressed))}.ok-native-list-trailing-button:focus-visible{outline:2px solid var(--nl-button-focus,var(--nl-accent))}.ok-native-list-trailing-button:disabled{opacity:.4;cursor:default}
|
|
467
|
+
.ok-native-list-icon-button.ok-native-list-tertiary-icon{box-sizing:border-box;flex:0 0 38px;width:38px;height:38px;margin:-7px;padding:6px;border:1px solid transparent;border-radius:9999px;color:var(--nl-icon-subdued);background:transparent}.ok-native-list-icon-button.ok-native-list-tertiary-icon:hover:not(:disabled){background:var(--nl-hover)}.ok-native-list-icon-button.ok-native-list-tertiary-icon:active:not(:disabled){background:var(--nl-pressed)}.ok-native-list-icon-button.ok-native-list-tertiary-icon:disabled{opacity:.4;cursor:default}
|
|
468
|
+
.ok-native-list-icon-button.ok-native-list-tertiary-icon:focus-visible:not(:disabled){outline:2px solid var(--nl-accent)}
|
|
469
|
+
.ok-native-list-identity-title-icon{flex:0 0 20px;width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;color:var(--nl-icon);font-size:20px}.ok-native-list-identity-title-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
466
470
|
.ok-native-list-account-row .ok-native-list-visual,.ok-native-list-account-action-row .ok-native-list-visual{width:32px;height:32px;flex-basis:32px}.ok-native-list-account-row .ok-native-list-visual>img,.ok-native-list-account-row .ok-native-list-visual-main,.ok-native-list-account-action-row .ok-native-list-visual>img,.ok-native-list-account-action-row .ok-native-list-visual-main{width:32px;height:32px}.ok-native-list-account-row .ok-native-list-visual>.ok-native-list-visual-corner{width:20px;height:20px;padding:2px}.ok-native-list-account-action-row .ok-native-list-visual{border-radius:8px!important}.ok-native-list-wallet-row .ok-native-list-title{color:var(--nl-secondary);font-size:12px;line-height:16px;font-weight:400;font-family:var(--nl-font-regular)}.ok-native-list-item[data-native-list-selected="true"]>.ok-native-list-wallet-row .ok-native-list-title{color:var(--nl-primary)}.ok-native-list-account-row .ok-native-list-title{font-size:16px;line-height:20px;font-weight:400;font-family:var(--nl-font-regular)}.ok-native-list-account-row .ok-native-list-secondary{font-size:14px;line-height:20px;font-weight:400;font-family:var(--nl-font-regular)}
|
|
467
471
|
.ok-native-list-flex{display:flex;flex:1;min-width:0;flex-direction:column;justify-content:center}.ok-native-list-title{font-size:15px;line-height:20px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:var(--nl-font-semibold)}.ok-native-list-secondary{font-size:13px;line-height:18px;color:var(--nl-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ok-native-list-tertiary{color:var(--nl-secondary)}.ok-native-list-info{color:var(--nl-info)}
|
|
468
472
|
.ok-native-list-identity-row .ok-native-list-title,.ok-native-list-identity-row .ok-native-list-amounts>span:first-child{font-size:16px;line-height:20px}.ok-native-list-identity-row .ok-native-list-secondary{font-size:14px;line-height:20px}
|
|
469
473
|
.ok-native-list-value{font-size:14px;line-height:20px;font-weight:500;white-space:nowrap;font-family:var(--nl-font-medium)}.ok-native-list-time{font-size:11px;line-height:16px;color:var(--nl-secondary);align-self:flex-start}.ok-native-list-amounts{display:flex;flex-direction:column;align-items:flex-end;min-width:0}.ok-native-list-actions{display:flex;gap:16px;margin-top:6px}
|
|
470
474
|
.ok-native-list-action-button{appearance:none;border:0;background:transparent;padding:2px;color:var(--nl-accent);cursor:pointer;font:600 12px/16px var(--nl-font-semibold)}.ok-native-list-action-button[data-tone="danger"]{color:var(--nl-negative)}.ok-native-list-action-button:disabled{opacity:.5;cursor:default}
|
|
471
|
-
.ok-native-list-visual{position:relative;flex:0 0 40px;width:40px;height:40px;border-radius:20px;overflow:visible;background:var(--nl-strong)}.ok-native-list-visual>img,.ok-native-list-visual-main{display:block;width:40px;height:40px;border-radius:inherit;object-fit:cover}.ok-native-list-visual-fallback{display:flex;width:100%;height:100%;align-items:center;justify-content:center;border-radius:inherit;color:var(--nl-primary);font-size:15px;font-weight:600;overflow:hidden;font-family:var(--nl-font-semibold)}.ok-native-list-visual>.ok-native-list-visual-corner{position:absolute;right:-4px;bottom:-4px;width:18px;height:18px;padding:2px;border-radius:50%;background:var(--nl-row);object-fit:cover}.ok-native-list-stacked{display:flex;align-items:center;width:48px;flex-basis:48px}.ok-native-list-stacked img{width:28px;height:28px;border:2px solid var(--nl-row);border-radius:50%;object-fit:cover;margin-left:-10px}.ok-native-list-stacked img:first-child{margin-left:0}
|
|
475
|
+
.ok-native-list-visual{position:relative;flex:0 0 40px;width:40px;height:40px;border-radius:20px;overflow:visible;background:var(--nl-strong)}.ok-native-list-visual>img,.ok-native-list-visual-main{display:block;width:40px;height:40px;border-radius:inherit;object-fit:cover}.ok-native-list-visual-fallback{display:flex;width:100%;height:100%;align-items:center;justify-content:center;border-radius:inherit;color:var(--nl-primary);font-size:15px;font-weight:600;overflow:hidden;font-family:var(--nl-font-semibold)}.ok-native-list-image-skeleton{position:absolute;inset:0;border-radius:inherit;pointer-events:none;animation:ok-native-list-skeleton-light 1.5s linear infinite alternate}.ok-native-list-image-skeleton[data-dark="true"]{animation-name:ok-native-list-skeleton-dark}@keyframes ok-native-list-skeleton-light{0%{background-color:#fafafa}100%{background-color:#cdcdcd}}@keyframes ok-native-list-skeleton-dark{0%{background-color:#111111}100%{background-color:#333333}}@media(prefers-reduced-motion:reduce){.ok-native-list-image-skeleton{animation:none;background-color:var(--nl-strong)}}.ok-native-list-visual>.ok-native-list-visual-corner{position:absolute;right:-4px;bottom:-4px;width:18px;height:18px;padding:2px;border-radius:50%;background:var(--nl-row);object-fit:cover}.ok-native-list-stacked{display:flex;align-items:center;width:48px;flex-basis:48px}.ok-native-list-stacked img{width:28px;height:28px;border:2px solid var(--nl-row);border-radius:50%;object-fit:cover;margin-left:-10px}.ok-native-list-stacked img:first-child{margin-left:0}
|
|
472
476
|
.ok-native-list-accessories{display:flex;align-items:center;gap:10px;min-width:0}.ok-native-list-accessory{font-size:14px;color:var(--nl-primary);white-space:nowrap}.ok-native-list-accessory-secondary{color:var(--nl-secondary)}.ok-native-list-icon-button{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:24px;border:0;background:transparent;color:var(--nl-icon);font-size:20px;line-height:1;font-weight:500;cursor:pointer;font-family:var(--nl-font-medium)}.ok-native-list-checkbox{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:20px;height:20px;border:2px solid color-mix(in srgb,var(--nl-primary) 19%,transparent);border-radius:5px;background:var(--nl-row);cursor:pointer}.ok-native-list-checkbox[data-state="checked"],.ok-native-list-checkbox[data-state="indeterminate"]{border-color:transparent;background:var(--nl-primary)}.ok-native-list-checkbox[data-state="checked"]::after{content:"";width:6px;height:10px;margin-top:-2px;border-right:2px solid var(--nl-row);border-bottom:2px solid var(--nl-row);transform:rotate(45deg)}.ok-native-list-checkbox[data-state="indeterminate"]::after{content:"";width:8px;height:2px;border-radius:1px;background:var(--nl-row)}.ok-native-list-spinner{width:16px;height:16px;border:2px solid var(--nl-separator);border-top-color:var(--nl-primary);border-radius:50%;animation:ok-native-list-spin .8s linear infinite}@keyframes ok-native-list-spin{to{transform:rotate(360deg)}}
|
|
473
|
-
.ok-native-list-
|
|
477
|
+
.ok-native-list-icon-button.ok-native-list-decorative-refresh{min-width:16px;width:16px;height:16px}
|
|
478
|
+
.ok-native-list-badge{display:inline-flex;align-items:center;max-width:100%;height:18px;padding:0 5px;border-radius:5px;background:color-mix(in srgb,var(--nl-accent) 12%,transparent);color:var(--nl-accent);font-size:11px;line-height:18px;white-space:nowrap}.ok-native-list-badge[data-tone="danger"]{background:var(--nl-critical);color:var(--nl-negative)}.ok-native-list-badge[data-tone="success"]{background:var(--nl-success-background,color-mix(in srgb,var(--nl-positive) 12%,transparent));color:var(--nl-positive)}.ok-native-list-section>.ok-native-list-badge[data-tone="success"]{box-sizing:border-box;height:20px;padding:2px 8px;border-radius:4px;font:500 12px/16px var(--nl-font-medium)}.ok-native-list-badges{display:inline-flex;gap:4px;margin-left:6px;vertical-align:middle}
|
|
479
|
+
.ok-native-list-identity-row .ok-native-list-badge[data-tone="neutral"]{height:20px;box-sizing:border-box;padding:2px 8px;border-radius:4px;background:var(--nl-strong);color:var(--nl-secondary);font-size:12px;line-height:16px;font-weight:500;font-family:var(--nl-font-medium)}
|
|
474
480
|
.ok-native-list-section{padding:0 8px;background:var(--nl-bg);gap:8px}.ok-native-list-section[data-variant="summary"]{padding:0 20px}.ok-native-list-section[data-variant="gallery"]{padding:0 12px}.ok-native-list-section[data-variant="history"]{padding:0 8px}.ok-native-list-section-title{font-size:13px;line-height:18px;font-weight:700;color:var(--nl-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:var(--nl-font-bold)}.ok-native-list-section[data-variant="summary"] .ok-native-list-section-title{font-size:16px;font-weight:500;color:var(--nl-primary);font-family:var(--nl-font-medium)}.ok-native-list-section[data-variant="gallery"] .ok-native-list-section-title{font-size:16px;color:var(--nl-primary)}.ok-native-list-section[data-variant="history"] .ok-native-list-section-title{font-size:12px;line-height:16px;letter-spacing:0.8px}.ok-native-list-section-value{margin-left:auto}
|
|
475
481
|
.ok-native-list-action-row{justify-content:space-between;padding:0 16px}.ok-native-list-action-title{font-size:15px;font-weight:600;color:var(--nl-accent);font-family:var(--nl-font-semibold)}.ok-native-list-action-title[data-tone="danger"]{color:var(--nl-negative)}
|
|
482
|
+
.ok-native-list-button-group{padding:0;gap:10px;overflow:visible}.ok-native-list-block-button{position:relative;display:flex;flex:1 1 0;min-width:0;min-height:48px;align-items:center;justify-content:center;gap:8px;padding:12px 8px;border:1px solid color-mix(in srgb,var(--nl-info) 35%,transparent);border-radius:12px;background:transparent;color:var(--nl-info);font:500 14px/20px var(--nl-font-medium);cursor:pointer}.ok-native-list-block-button>span:not(.ok-native-list-spinner){min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ok-native-list-block-button>.ok-native-list-spinner{position:static;flex:0 0 20px;width:20px;height:20px;border-top-color:var(--nl-info)}.ok-native-list-block-button:hover:not(:disabled){background:color-mix(in srgb,var(--nl-info) 10%,transparent);border-color:var(--nl-info)}.ok-native-list-block-button:active:not(:disabled){background:color-mix(in srgb,var(--nl-info) 17%,transparent)}.ok-native-list-block-button:focus-visible{outline:2px solid var(--nl-info);outline-offset:1px}.ok-native-list-block-button:disabled{opacity:.4;cursor:default}
|
|
476
483
|
.ok-native-list-account-action-row{justify-content:flex-start;gap:12px;padding:0 12px}.ok-native-list-account-action-row .ok-native-list-action-title{color:var(--nl-secondary);font-size:16px;line-height:24px;font-weight:400;font-family:var(--nl-font-regular)}
|
|
477
484
|
.ok-native-list-system{justify-content:center;padding:8px 12px;background:var(--nl-bg);color:var(--nl-secondary);cursor:default}.ok-native-list-system[data-variant="retry"],.ok-native-list-system[data-variant="noMatch"],.ok-native-list-system[data-variant="end"]{justify-content:flex-start}.ok-native-list-system[data-variant="retry"]{cursor:pointer}
|
|
478
485
|
.ok-native-list-rail{padding:4px;gap:6px;border-radius:8px}.ok-native-list-rail .ok-native-list-visual{width:20px;height:20px;flex-basis:20px}.ok-native-list-rail .ok-native-list-visual>img,.ok-native-list-rail .ok-native-list-visual-main{width:20px;height:20px}.ok-native-list-rail-title{font-size:12px;font-weight:500;white-space:nowrap;font-family:var(--nl-font-medium)}
|
|
@@ -521,6 +528,7 @@ export const WEB_LIST_CSS = `
|
|
|
521
528
|
.ok-native-list-root .ok-native-list-item>[data-nl-container-background="true"],.ok-native-list-root .ok-native-list-wallet-member>[data-nl-container-background="true"]{background:var(--nl-container-background)}
|
|
522
529
|
.ok-native-list-root [data-nl-container-border="true"]{position:relative}
|
|
523
530
|
.ok-native-list-root [data-nl-container-border="true"]::before{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 var(--nl-container-border-width) var(--nl-container-border-color);z-index:2;pointer-events:none}
|
|
531
|
+
.ok-native-list-root [data-nl-inline-warning="true"][data-nl-container-border="true"]::before{box-shadow:none;border-block:var(--nl-container-border-width) solid var(--nl-container-border-color);border-inline:0;border-radius:0}
|
|
524
532
|
.ok-native-list-root .ok-native-list-item[data-native-list-row-press-enabled="true"]:hover>[data-nl-container-background="true"],.ok-native-list-root .ok-native-list-item[data-native-list-row-press-enabled="true"]:active>[data-nl-container-background="true"],.ok-native-list-root .ok-native-list-wallet-member:hover>[data-nl-container-background="true"],.ok-native-list-root .ok-native-list-wallet-member:active>[data-nl-container-background="true"]{background:var(--nl-pressed)}
|
|
525
533
|
`;
|
|
526
534
|
function createElement(document, tag, className, text) {
|
|
@@ -718,6 +726,38 @@ function paintSelectorImageBackground(image, frame, inset = 0) {
|
|
|
718
726
|
|
|
719
727
|
// OneKey patch: use source SVG paths for selector actions and wallet provider marks.
|
|
720
728
|
const selectorIcons = {
|
|
729
|
+
RefreshCcwOutline: {
|
|
730
|
+
viewBox: '0 0 24 24',
|
|
731
|
+
paths: [{
|
|
732
|
+
d: 'M5 12a7 7 0 0 0 7 7 7.15 7.15 0 0 0 4.955-2h-2.943v-2h6v6h-2v-2.257A9.148 9.148 0 0 1 12 21a9 9 0 0 1-9-9v-1h2v1Zm1-6.754A9.148 9.148 0 0 1 12 3a9 9 0 0 1 9 9v1h-2v-1a7 7 0 0 0-7-7 7.15 7.15 0 0 0-4.955 2H10v2H4V3h2v2.246Z',
|
|
733
|
+
fill: 'currentColor',
|
|
734
|
+
fillRule: 'nonzero',
|
|
735
|
+
opacity: 1
|
|
736
|
+
}]
|
|
737
|
+
},
|
|
738
|
+
TicketOutline: {
|
|
739
|
+
viewBox: '0 0 24 24',
|
|
740
|
+
paths: [{
|
|
741
|
+
d: 'M16 17.01h-2V15h2v2.01Zm0-4h-2V11h2v2.01Zm0-4h-2V7h2v2.01Z',
|
|
742
|
+
fill: 'currentColor',
|
|
743
|
+
fillRule: 'nonzero',
|
|
744
|
+
opacity: 1
|
|
745
|
+
}, {
|
|
746
|
+
d: 'm22 9.927-.629.252c-1.661.665-1.661 2.977 0 3.642l.629.252V20H2v-5.927l.629-.252c1.661-.665 1.661-2.977 0-3.642L2 9.927V4h20v5.927ZM4 8.636c2.5 1.52 2.499 5.207 0 6.727V18h16v-2.637c-2.499-1.52-2.5-5.208 0-6.727V6H4v2.636Z',
|
|
747
|
+
fill: 'currentColor',
|
|
748
|
+
fillRule: 'evenodd',
|
|
749
|
+
opacity: 1
|
|
750
|
+
}]
|
|
751
|
+
},
|
|
752
|
+
GasSolid: {
|
|
753
|
+
viewBox: '0 0 24 24',
|
|
754
|
+
paths: [{
|
|
755
|
+
d: 'M15 9h4v7h1V8.414L17.586 6 19 4.586l3 3V18h-5v-7h-2v8h1v2H2v-2h1V3h12zM6 9v2h6V9z',
|
|
756
|
+
fill: 'currentColor',
|
|
757
|
+
fillRule: 'evenodd',
|
|
758
|
+
opacity: 1
|
|
759
|
+
}]
|
|
760
|
+
},
|
|
721
761
|
CryptoCoinOutline: {
|
|
722
762
|
viewBox: '0 0 24 24',
|
|
723
763
|
paths: [{
|
|
@@ -962,6 +1002,7 @@ function applySelectorIcon(element, name) {
|
|
|
962
1002
|
}
|
|
963
1003
|
function iconGlyph(name) {
|
|
964
1004
|
const normalized = name.toLocaleLowerCase();
|
|
1005
|
+
if (normalized === 'dotversolid') return '⋮';
|
|
965
1006
|
if (normalized.includes('chevron')) {
|
|
966
1007
|
if (normalized.includes('top')) return '⌃';
|
|
967
1008
|
if (normalized.includes('bottom')) return '⌄';
|
|
@@ -1009,6 +1050,8 @@ function createVisual(context, visual, selectorPresentation) {
|
|
|
1009
1050
|
const showsSourcePlaceholder = !!source && source.loadingStrategy !== undefined && source.loadingStrategy !== 'none';
|
|
1010
1051
|
frame.style.background = showsSourcePlaceholder ? 'var(--nl-strong)' : visualBackground;
|
|
1011
1052
|
const fallbackIcon = 'fallbackIcon' in visual ? visual.fallbackIcon : undefined;
|
|
1053
|
+
const fallbackBackground = fallbackIcon?.backgroundColor ?? 'var(--nl-strong)';
|
|
1054
|
+
if (!source && fallbackIcon?.backgroundColor) frame.style.background = fallbackBackground;
|
|
1012
1055
|
const handlesSourceFallback = showsSourcePlaceholder && (fallbackIcon !== undefined || 'fallbackText' in visual);
|
|
1013
1056
|
const image = source ? createImage(context, source) : undefined;
|
|
1014
1057
|
if (image) {
|
|
@@ -1022,6 +1065,24 @@ function createVisual(context, visual, selectorPresentation) {
|
|
|
1022
1065
|
if (image.complete && image.naturalWidth > 0) restoreBackground();
|
|
1023
1066
|
}
|
|
1024
1067
|
if (selectorPresentation) paintSelectorImageBackground(image, frame);
|
|
1068
|
+
if (source?.loadingStrategy === 'skeleton' && !(image.complete && image.naturalWidth > 0)) {
|
|
1069
|
+
const skeleton = createElement(context.document, 'span', 'ok-native-list-image-skeleton');
|
|
1070
|
+
const background = resolvedTheme(context.snapshot).background;
|
|
1071
|
+
const rgb = /^#([0-9a-f]{6})/i.exec(background)?.[1];
|
|
1072
|
+
if (rgb) {
|
|
1073
|
+
const red = Number.parseInt(rgb.slice(0, 2), 16);
|
|
1074
|
+
const green = Number.parseInt(rgb.slice(2, 4), 16);
|
|
1075
|
+
const blue = Number.parseInt(rgb.slice(4, 6), 16);
|
|
1076
|
+
if (red * 299 + green * 587 + blue * 114 < 128_000) skeleton.dataset.dark = 'true';
|
|
1077
|
+
}
|
|
1078
|
+
frame.appendChild(skeleton);
|
|
1079
|
+
image.addEventListener('load', () => skeleton.remove(), {
|
|
1080
|
+
once: true
|
|
1081
|
+
});
|
|
1082
|
+
image.addEventListener('error', () => skeleton.remove(), {
|
|
1083
|
+
once: true
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1025
1086
|
} else if (!source || showsSourcePlaceholder) {
|
|
1026
1087
|
frame.appendChild(createElement(context.document, 'span', 'ok-native-list-visual-fallback', 'fallbackText' in visual ? visual.fallbackText ?? '' : ''));
|
|
1027
1088
|
}
|
|
@@ -1045,11 +1106,19 @@ function createVisual(context, visual, selectorPresentation) {
|
|
|
1045
1106
|
}
|
|
1046
1107
|
frame.querySelector('.ok-native-list-visual-fallback:not(.ok-native-list-visual-corner)')?.remove();
|
|
1047
1108
|
const fallback = createElement(context.document, 'span', 'ok-native-list-visual-fallback', fallbackIcon ? undefined : 'fallbackText' in visual ? visual.fallbackText ?? '' : '');
|
|
1109
|
+
if ('fallbackTextColor' in visual && visual.fallbackTextColor && !fallbackIcon) fallback.style.color = visual.fallbackTextColor;
|
|
1048
1110
|
if (fallbackIcon) {
|
|
1049
1111
|
applySelectorIcon(fallback, fallbackIcon.name);
|
|
1050
1112
|
if (fallbackIcon.tintColor) fallback.style.color = fallbackIcon.tintColor;
|
|
1113
|
+
if (fallbackIcon.size) {
|
|
1114
|
+
const svg = fallback.querySelector('svg');
|
|
1115
|
+
if (svg) {
|
|
1116
|
+
svg.style.width = `${fallbackIcon.size}px`;
|
|
1117
|
+
svg.style.height = `${fallbackIcon.size}px`;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1051
1120
|
}
|
|
1052
|
-
fallback.style.backgroundColor = 'var(--nl-image-fallback-background, transparent)';
|
|
1121
|
+
if (fallbackIcon?.backgroundColor) frame.style.background = fallbackBackground;else fallback.style.backgroundColor = 'var(--nl-image-fallback-background, transparent)';
|
|
1053
1122
|
frame.prepend(fallback);
|
|
1054
1123
|
};
|
|
1055
1124
|
if (image) image.addEventListener('error', showFallback, {
|
|
@@ -1059,6 +1128,9 @@ function createVisual(context, visual, selectorPresentation) {
|
|
|
1059
1128
|
if ('borderStyle' in visual && visual.borderStyle === 'dashed') {
|
|
1060
1129
|
frame.style.border = '2px dashed ' + (visual.borderColor ?? 'var(--nl-disabled)');
|
|
1061
1130
|
frame.style.boxSizing = 'border-box';
|
|
1131
|
+
} else if ('borderColor' in visual && visual.borderColor) {
|
|
1132
|
+
frame.style.border = '1px solid ' + visual.borderColor;
|
|
1133
|
+
frame.style.boxSizing = 'border-box';
|
|
1062
1134
|
}
|
|
1063
1135
|
if ('overlays' in visual) visual.overlays?.forEach(overlay => {
|
|
1064
1136
|
const corner = createElement(context.document, 'span', 'ok-native-list-visual-overlay', overlay.text);
|
|
@@ -1072,6 +1144,12 @@ function createVisual(context, visual, selectorPresentation) {
|
|
|
1072
1144
|
corner.style.lineHeight = '16px';
|
|
1073
1145
|
applyTextWeight(corner, '400');
|
|
1074
1146
|
}
|
|
1147
|
+
if (overlay.fontWeight) applyTextWeight(corner, {
|
|
1148
|
+
regular: 400,
|
|
1149
|
+
medium: 500,
|
|
1150
|
+
semibold: 600,
|
|
1151
|
+
bold: 700
|
|
1152
|
+
}[overlay.fontWeight]);
|
|
1075
1153
|
if (isWalletText || overlay.width !== undefined || overlay.height !== undefined) corner.style.borderRadius = '9999px';
|
|
1076
1154
|
const offsetX = String(-(overlay.offsetX ?? overlay.offset ?? 2)) + 'px';
|
|
1077
1155
|
const offsetY = String(-(overlay.offsetY ?? overlay.offset ?? 2)) + 'px';
|
|
@@ -1087,7 +1165,20 @@ function createVisual(context, visual, selectorPresentation) {
|
|
|
1087
1165
|
if (overlay.image) {
|
|
1088
1166
|
const overlayImage = createImage(context, overlay.image);
|
|
1089
1167
|
if (overlayImage) {
|
|
1168
|
+
if ((overlay.padding ?? 0) > 0 && (overlay.width ?? size) === (overlay.height ?? size)) overlayImage.style.borderRadius = '50%';
|
|
1090
1169
|
corner.appendChild(overlayImage);
|
|
1170
|
+
if (overlay.fallbackIcon) {
|
|
1171
|
+
overlayImage.addEventListener('error', () => {
|
|
1172
|
+
disposeWebImageRetries(overlayImage);
|
|
1173
|
+
overlayImage.remove();
|
|
1174
|
+
const glyph = createElement(context.document, 'span', 'ok-native-list-overlay-fallback');
|
|
1175
|
+
applySelectorIcon(glyph, overlay.fallbackIcon.name);
|
|
1176
|
+
if (overlay.fallbackIcon?.tintColor) glyph.style.color = overlay.fallbackIcon.tintColor;
|
|
1177
|
+
corner.appendChild(glyph);
|
|
1178
|
+
}, {
|
|
1179
|
+
once: true
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1091
1182
|
if (selectorPresentation) paintSelectorImageBackground(overlayImage, corner, overlay.padding ?? 0);
|
|
1092
1183
|
}
|
|
1093
1184
|
} else if (overlay.name) applySelectorIcon(corner, overlay.name);
|
|
@@ -1167,7 +1258,23 @@ function markActionAnchorSource(element, source, slot) {
|
|
|
1167
1258
|
|
|
1168
1259
|
// OneKey patch: the compact zero-count digits share the amount baseline.
|
|
1169
1260
|
|
|
1170
|
-
function createAccessory(context, rowKey, accessory, slot) {
|
|
1261
|
+
function createAccessory(context, rowKey, accessory, slot, rowDisabled) {
|
|
1262
|
+
if (accessory.kind === 'button') {
|
|
1263
|
+
const element = createElement(context.document, 'button', 'ok-native-list-trailing-button', accessory.label);
|
|
1264
|
+
element.type = 'button';
|
|
1265
|
+
element.disabled = Boolean(rowDisabled || accessory.disabled);
|
|
1266
|
+
element.setAttribute('aria-disabled', String(element.disabled));
|
|
1267
|
+
element.setAttribute('aria-label', accessory.accessibilityLabel ?? accessory.label);
|
|
1268
|
+
setData(element, 'testid', accessory.testID);
|
|
1269
|
+
setData(element, 'nativeListAction', accessory.actionKey);
|
|
1270
|
+
markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
1271
|
+
if (accessory.textColor) element.style.setProperty('--nl-button-text', accessory.textColor);
|
|
1272
|
+
if (accessory.backgroundColor) element.style.setProperty('--nl-button-bg', accessory.backgroundColor);
|
|
1273
|
+
if (accessory.pressedBackgroundColor) element.style.setProperty('--nl-button-pressed', accessory.pressedBackgroundColor);
|
|
1274
|
+
if (accessory.hoverBackgroundColor) element.style.setProperty('--nl-button-hover', accessory.hoverBackgroundColor);
|
|
1275
|
+
if (accessory.focusRingColor) element.style.setProperty('--nl-button-focus', accessory.focusRingColor);
|
|
1276
|
+
return element;
|
|
1277
|
+
}
|
|
1171
1278
|
if (accessory.kind === 'checkbox') {
|
|
1172
1279
|
const element = createCheckbox(context, rowKey, accessory);
|
|
1173
1280
|
markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
@@ -1176,8 +1283,19 @@ function createAccessory(context, rowKey, accessory, slot) {
|
|
|
1176
1283
|
if (accessory.kind === 'icon') {
|
|
1177
1284
|
const element = createIconAction(context, accessory.name, accessory.actionKey, accessory.disabled, accessory.tintColor);
|
|
1178
1285
|
markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
1286
|
+
if (accessory.name === 'RefreshCcwOutline' && !accessory.actionKey) {
|
|
1287
|
+
element.classList.add('ok-native-list-decorative-refresh');
|
|
1288
|
+
const glyph = element.querySelector('svg');
|
|
1289
|
+
glyph?.setAttribute('width', '16');
|
|
1290
|
+
glyph?.setAttribute('height', '16');
|
|
1291
|
+
}
|
|
1292
|
+
if (accessory.buttonStyle === 'tertiary') {
|
|
1293
|
+
element.classList.add('ok-native-list-tertiary-icon');
|
|
1294
|
+
setData(element, 'nativeListAnchorInset', 7);
|
|
1295
|
+
}
|
|
1179
1296
|
setData(element, 'testid', accessory.testID);
|
|
1180
1297
|
if (accessory.hoverActionKey) setData(element, 'nativeListHoverAction', accessory.hoverActionKey);
|
|
1298
|
+
if (accessory.hoverActionKey && accessory.buttonStyle === 'tertiary') setData(element, 'nativeListIconHelp', true);
|
|
1181
1299
|
if (accessory.accessibilityLabel) element.setAttribute('aria-label', accessory.accessibilityLabel);
|
|
1182
1300
|
const row = context.snapshot.rows[context.itemIndex];
|
|
1183
1301
|
if (row && 'presentation' in row && row.presentation === 'accountSelector') {
|
|
@@ -1210,8 +1328,27 @@ function createAccessory(context, rowKey, accessory, slot) {
|
|
|
1210
1328
|
{
|
|
1211
1329
|
const primary = createElement(context.document, 'span', undefined, accessory.primary);
|
|
1212
1330
|
primary.style.color = toneColor(accessory.primaryTone, 'primary');
|
|
1331
|
+
applyValueSegments(primary, accessory.primaryTextSegments, 16, 20, 500);
|
|
1332
|
+
if (accessory.primaryFontWeight === 'medium') applyTextWeight(primary, 500);
|
|
1333
|
+
if (accessory.primaryHelp) {
|
|
1334
|
+
const help = accessory.primaryHelp;
|
|
1335
|
+
primary.tabIndex = 0;
|
|
1336
|
+
primary.setAttribute('role', 'button');
|
|
1337
|
+
if (help.presentation === 'tooltip') {
|
|
1338
|
+
setData(primary, 'nativeListHoverAction', help.actionKey);
|
|
1339
|
+
setData(primary, 'nativeListIconHelp', true);
|
|
1340
|
+
} else {
|
|
1341
|
+
setData(primary, 'nativeListAction', help.actionKey);
|
|
1342
|
+
}
|
|
1343
|
+
if (help.underline === 'dashed') {
|
|
1344
|
+
primary.style.textDecoration = 'underline dashed';
|
|
1345
|
+
primary.style.textUnderlineOffset = '4px';
|
|
1346
|
+
}
|
|
1347
|
+
markActionAnchorSource(primary, 'trailingAccessory', slot);
|
|
1348
|
+
}
|
|
1213
1349
|
const secondary = createElement(context.document, 'span', 'ok-native-list-secondary', accessory.secondary);
|
|
1214
1350
|
secondary.style.color = toneColor(accessory.secondaryTone, 'secondary');
|
|
1351
|
+
applyValueSegments(secondary, accessory.secondaryTextSegments, 14, 20, 400);
|
|
1215
1352
|
element.replaceChildren(primary, '\n', secondary);
|
|
1216
1353
|
element.classList.add('ok-native-list-amounts');
|
|
1217
1354
|
break;
|
|
@@ -1239,10 +1376,10 @@ function createAccessory(context, rowKey, accessory, slot) {
|
|
|
1239
1376
|
if (actionKey) markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
1240
1377
|
return element;
|
|
1241
1378
|
}
|
|
1242
|
-
function rendererPrimitives(context) {
|
|
1379
|
+
function rendererPrimitives(context, rowDisabled) {
|
|
1243
1380
|
return {
|
|
1244
1381
|
background: resolvedTheme(context.snapshot).background,
|
|
1245
|
-
accessory: (key, descriptor, slot) => createAccessory(context, key, descriptor, slot),
|
|
1382
|
+
accessory: (key, descriptor, slot) => createAccessory(context, key, descriptor, slot, rowDisabled),
|
|
1246
1383
|
visual: (source, presentation) => createVisual(context, source, presentation),
|
|
1247
1384
|
thumbnail: source => createImage(context, source, 'ok-native-list-thumbnail'),
|
|
1248
1385
|
textStyle: applyTextStyleToSlot,
|
|
@@ -1252,7 +1389,7 @@ function rendererPrimitives(context) {
|
|
|
1252
1389
|
};
|
|
1253
1390
|
}
|
|
1254
1391
|
export function createRowBody(context, row) {
|
|
1255
|
-
return rowRenderer(row).create(context.document, rendererPrimitives(context));
|
|
1392
|
+
return rowRenderer(row).create(context.document, rendererPrimitives(context, Boolean(row.disabled)));
|
|
1256
1393
|
}
|
|
1257
1394
|
export class NativeListWebEngine {
|
|
1258
1395
|
rows = [];
|
|
@@ -1270,6 +1407,7 @@ export class NativeListWebEngine {
|
|
|
1270
1407
|
rail: [],
|
|
1271
1408
|
mediaTile: [],
|
|
1272
1409
|
action: [],
|
|
1410
|
+
buttonGroup: [],
|
|
1273
1411
|
system: [],
|
|
1274
1412
|
activity: [],
|
|
1275
1413
|
dataRow: [],
|
|
@@ -1296,6 +1434,16 @@ export class NativeListWebEngine {
|
|
|
1296
1434
|
lastViewportWidth = -1;
|
|
1297
1435
|
lastViewportHeight = -1;
|
|
1298
1436
|
destroyed = false;
|
|
1437
|
+
hasAppliedSnapshot = false;
|
|
1438
|
+
structuralRevision = 0;
|
|
1439
|
+
structuralAnimations = [];
|
|
1440
|
+
structuralScrollInterrupted = false;
|
|
1441
|
+
reactFooterHeight = 0;
|
|
1442
|
+
structuralFooterCompensation = 0;
|
|
1443
|
+
structuralFooterExpansion = 0;
|
|
1444
|
+
structuralFooterFromHeight = 0;
|
|
1445
|
+
structuralProgress = 0;
|
|
1446
|
+
structuralPrefixTransition = false;
|
|
1299
1447
|
sectionIndexAlignStart = false;
|
|
1300
1448
|
// Renderers report intrinsic height after browser text wrapping.
|
|
1301
1449
|
measuredRendererHeights = new Map();
|
|
@@ -1384,6 +1532,9 @@ export class NativeListWebEngine {
|
|
|
1384
1532
|
});
|
|
1385
1533
|
}
|
|
1386
1534
|
(this.externalScrollHost ?? this.viewport).addEventListener('ok-collapsible-pager-cancel-scroll-command', this.handlePagerScrollCommandCancel);
|
|
1535
|
+
for (const event of ['wheel', 'pointerdown', 'touchstart']) (this.externalScrollHost ?? this.viewport).addEventListener(event, this.handleStructuralUserScroll, {
|
|
1536
|
+
passive: true
|
|
1537
|
+
});
|
|
1387
1538
|
this.viewport.addEventListener('scroll', this.handleScroll, {
|
|
1388
1539
|
passive: true
|
|
1389
1540
|
});
|
|
@@ -1399,6 +1550,7 @@ export class NativeListWebEngine {
|
|
|
1399
1550
|
this.root.addEventListener('pointercancel', this.handleMarketPointerEnd);
|
|
1400
1551
|
// OneKey patch: preserve web tooltip hover for section titles.
|
|
1401
1552
|
this.root.addEventListener('pointerover', this.handleTitlePointerOver);
|
|
1553
|
+
this.root.addEventListener('pointerdown', this.handleIconHelpPointerDown);
|
|
1402
1554
|
this.root.addEventListener('focusin', this.handleTitlePointerOver);
|
|
1403
1555
|
this.root.addEventListener('focusout', this.handleTitlePointerOut);
|
|
1404
1556
|
this.root.addEventListener('pointerout', this.handleTitlePointerOut);
|
|
@@ -1452,7 +1604,7 @@ export class NativeListWebEngine {
|
|
|
1452
1604
|
this.document.fonts?.addEventListener('loadingdone', this.handleWindowResize);
|
|
1453
1605
|
this.observeSectionIndexTransforms();
|
|
1454
1606
|
this.applyFontFamilies(fontFamiliesJson);
|
|
1455
|
-
this.
|
|
1607
|
+
this.applyValidatedSnapshot(this.snapshot);
|
|
1456
1608
|
}
|
|
1457
1609
|
validateStickyInset(value = 0) {
|
|
1458
1610
|
if (!Number.isFinite(value) || value < 0) throw new Error('webStickyInset must be finite and non-negative');
|
|
@@ -1522,8 +1674,285 @@ export class NativeListWebEngine {
|
|
|
1522
1674
|
return next;
|
|
1523
1675
|
});
|
|
1524
1676
|
if (!validated) return;
|
|
1677
|
+
this.applyValidatedSnapshot(validated);
|
|
1678
|
+
}
|
|
1679
|
+
applyValidatedSnapshot(validated) {
|
|
1680
|
+
this.pressedHelpElement = undefined;
|
|
1525
1681
|
this.invalidateActionAnchor('snapshot');
|
|
1526
|
-
|
|
1682
|
+
const transition = validated.structuralTransition;
|
|
1683
|
+
const isNewTransition = transition !== undefined && transition.id !== this.lastStructuralTransitionId;
|
|
1684
|
+
if (transition) this.lastStructuralTransitionId = transition.id;
|
|
1685
|
+
const nextRows = effectiveRows(validated);
|
|
1686
|
+
const changedKeys = this.rows.length !== nextRows.length || this.rows.some((row, index) => row.key !== nextRows[index]?.key);
|
|
1687
|
+
const incompatibleActivePrefix = this.structuralPrefixTransition && (validated.layout.kind !== this.snapshot.layout.kind || validated.layout.orientation !== this.snapshot.layout.orientation || nextRows.some((row, index) => row.height !== this.rows[index]?.height || row.style?.container?.height !== this.rows[index]?.style?.container?.height));
|
|
1688
|
+
const shouldAnimate = this.hasAppliedSnapshot && isNewTransition && changedKeys && (this.snapshot.layout.kind === 'linear' || this.snapshot.layout.kind === 'table') && this.snapshot.layout.orientation !== 'horizontal' && (validated.layout.kind === 'linear' || validated.layout.kind === 'table') && validated.layout.orientation !== 'horizontal' && (transition?.durationMs ?? 220) > 0 && !this.document.defaultView?.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
|
|
1689
|
+
if (shouldAnimate && transition) this.applyStructuralSnapshot(validated, transition);else {
|
|
1690
|
+
if (isNewTransition || changedKeys || incompatibleActivePrefix) this.cancelStructuralAnimation();
|
|
1691
|
+
this.setSnapshot(validated);
|
|
1692
|
+
}
|
|
1693
|
+
this.hasAppliedSnapshot = true;
|
|
1694
|
+
}
|
|
1695
|
+
cancelStructuralAnimation() {
|
|
1696
|
+
this.structuralRevision += 1;
|
|
1697
|
+
if (this.structuralFrame !== undefined) this.document.defaultView?.cancelAnimationFrame(this.structuralFrame);
|
|
1698
|
+
if (this.structuralFinish !== undefined) this.document.defaultView?.clearTimeout(this.structuralFinish);
|
|
1699
|
+
this.structuralFrame = undefined;
|
|
1700
|
+
this.structuralFinish = undefined;
|
|
1701
|
+
this.structuralAnimations.forEach(animation => animation.cancel());
|
|
1702
|
+
this.structuralAnimations = [];
|
|
1703
|
+
if (this.structuralTail) {
|
|
1704
|
+
disposeWebImageRetries(this.structuralTail.layer);
|
|
1705
|
+
this.structuralTail.layer.remove();
|
|
1706
|
+
this.structuralTail = undefined;
|
|
1707
|
+
}
|
|
1708
|
+
if (this.structuralContentOverflow !== undefined) {
|
|
1709
|
+
this.content.style.overflow = this.structuralContentOverflow;
|
|
1710
|
+
this.structuralContentOverflow = undefined;
|
|
1711
|
+
}
|
|
1712
|
+
this.structuralPrefixTransition = false;
|
|
1713
|
+
if (this.structuralFooterElement && this.structuralFooterStyles) {
|
|
1714
|
+
this.structuralFooterElement.style.marginBottom = this.structuralFooterStyles.marginBottom;
|
|
1715
|
+
this.structuralFooterElement.style.transform = this.structuralFooterStyles.transform;
|
|
1716
|
+
this.structuralFooterElement.style.clipPath = this.structuralFooterStyles.clipPath;
|
|
1717
|
+
}
|
|
1718
|
+
this.structuralFooterElement = undefined;
|
|
1719
|
+
this.structuralFooterStyles = undefined;
|
|
1720
|
+
this.structuralScrollInterrupted = false;
|
|
1721
|
+
this.structuralRenderedHeight = undefined;
|
|
1722
|
+
this.structuralTargetHeight = undefined;
|
|
1723
|
+
this.structuralFooterCompensation = 0;
|
|
1724
|
+
this.structuralFooterExpansion = 0;
|
|
1725
|
+
this.structuralProgress = 0;
|
|
1726
|
+
const owner = this.externalScrollHost ?? this.viewport;
|
|
1727
|
+
if (this.structuralAnchorStyles) {
|
|
1728
|
+
owner.style.overflowAnchor = this.structuralAnchorStyles.owner;
|
|
1729
|
+
this.content.style.overflowAnchor = this.structuralAnchorStyles.content;
|
|
1730
|
+
this.structuralAnchorStyles = undefined;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
handleStructuralUserScroll = event => {
|
|
1734
|
+
if (event.type === 'pointerdown' && event.target !== (this.externalScrollHost ?? this.viewport) && event.pointerType !== 'touch') return;
|
|
1735
|
+
this.structuralScrollInterrupted = true;
|
|
1736
|
+
if (this.structuralPrefixTransition) {
|
|
1737
|
+
this.cancelStructuralAnimation();
|
|
1738
|
+
this.recomputeLayout();
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
1741
|
+
updateStructuralTailWindow() {
|
|
1742
|
+
const tail = this.structuralTail;
|
|
1743
|
+
if (!tail) return;
|
|
1744
|
+
const visible = visibleWebLayoutItems(tail.layout, this.currentOffset(), this.viewportLength(), this.viewportLength() * OVERSCAN_VIEWPORTS).filter(item => item.index >= tail.firstIndex);
|
|
1745
|
+
const desired = new Set(visible.map(item => item.index));
|
|
1746
|
+
tail.mounted.forEach((element, index) => {
|
|
1747
|
+
if (desired.has(index)) return;
|
|
1748
|
+
disposeWebImageRetries(element);
|
|
1749
|
+
element.remove();
|
|
1750
|
+
tail.mounted.delete(index);
|
|
1751
|
+
});
|
|
1752
|
+
visible.forEach(item => {
|
|
1753
|
+
if (tail.mounted.has(item.index)) return;
|
|
1754
|
+
const row = tail.rows[item.index];
|
|
1755
|
+
if (!row) return;
|
|
1756
|
+
const element = createElement(this.document, 'div', 'ok-native-list-item');
|
|
1757
|
+
element.setAttribute('aria-hidden', 'true');
|
|
1758
|
+
element.style.pointerEvents = 'none';
|
|
1759
|
+
element.style.opacity = String((row.style?.container?.opacity ?? row.opacity ?? 1) * (row.disabled ? 0.5 : 1));
|
|
1760
|
+
const body = createRowBody({
|
|
1761
|
+
document: this.document,
|
|
1762
|
+
snapshot: tail.snapshot,
|
|
1763
|
+
selectedKeys: selectionStateFromSnapshot(tail.snapshot).selectedKeys,
|
|
1764
|
+
itemIndex: item.index
|
|
1765
|
+
}, row);
|
|
1766
|
+
applyRowStyle(body, row);
|
|
1767
|
+
element.append(body);
|
|
1768
|
+
this.positionElement(element, item);
|
|
1769
|
+
tail.layer.append(element);
|
|
1770
|
+
tail.mounted.set(item.index, element);
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
writeStructuralHeight(height) {
|
|
1774
|
+
if (this.externalScrollHost) this.writeExternalHeight(height);else this.content.style.height = `${height}px`;
|
|
1775
|
+
}
|
|
1776
|
+
reactFooterElement() {
|
|
1777
|
+
return this.contentBounds?.querySelector('[data-testid="native-list-footer-slot"]');
|
|
1778
|
+
}
|
|
1779
|
+
readReactFooterHeight() {
|
|
1780
|
+
return this.reactFooterElement()?.getBoundingClientRect().height ?? 0;
|
|
1781
|
+
}
|
|
1782
|
+
applyStructuralFooterVisual(progress) {
|
|
1783
|
+
const footer = this.structuralFooterElement;
|
|
1784
|
+
if (!footer || this.structuralFooterExpansion <= 0) return;
|
|
1785
|
+
const hidden = this.structuralFooterExpansion * (1 - progress);
|
|
1786
|
+
footer.style.marginBottom = `${-hidden}px`;
|
|
1787
|
+
footer.style.transform = `translateY(${-hidden}px)`;
|
|
1788
|
+
footer.style.clipPath = `inset(${hidden}px 0 0 0)`;
|
|
1789
|
+
}
|
|
1790
|
+
applyStructuralSnapshot(next, transition) {
|
|
1791
|
+
const owner = this.externalScrollHost ?? this.viewport;
|
|
1792
|
+
const oldOffset = owner.scrollTop;
|
|
1793
|
+
const oldScrollHeight = owner.scrollHeight;
|
|
1794
|
+
const oldHeight = this.structuralRenderedHeight ?? (this.content.getBoundingClientRect().height || this.layout.contentHeight);
|
|
1795
|
+
const nextFooterHeight = this.readReactFooterHeight();
|
|
1796
|
+
const oldFooterHeight = this.structuralRenderedHeight === undefined ? this.reactFooterHeight : this.structuralFooterFromHeight + (this.reactFooterHeight - this.structuralFooterFromHeight) * this.structuralProgress;
|
|
1797
|
+
const footerDifference = oldFooterHeight - nextFooterHeight;
|
|
1798
|
+
const startHeight = oldHeight + Math.max(0, footerDifference);
|
|
1799
|
+
const oldSnapshot = this.snapshot;
|
|
1800
|
+
const oldRows = this.rows;
|
|
1801
|
+
const oldLayout = this.layout;
|
|
1802
|
+
const oldItems = oldLayout.items;
|
|
1803
|
+
const nextRows = effectiveRows(next);
|
|
1804
|
+
const prefixCount = Math.min(oldRows.length, nextRows.length);
|
|
1805
|
+
const prefixTailChange = oldSnapshot.layout.kind === next.layout.kind && oldSnapshot.layout.orientation === next.layout.orientation && oldRows.length !== nextRows.length && oldRows.slice(0, prefixCount).every((row, index) => row.key === nextRows[index]?.key);
|
|
1806
|
+
const oldPositions = new Map();
|
|
1807
|
+
this.mounted.forEach((element, index) => {
|
|
1808
|
+
const row = this.rows[index];
|
|
1809
|
+
if (row) oldPositions.set(row.key, element.getBoundingClientRect().top);
|
|
1810
|
+
});
|
|
1811
|
+
const nextKeys = new Set(effectiveRows(next).map(row => row.key));
|
|
1812
|
+
const visibleOffset = this.currentOffset();
|
|
1813
|
+
const visibleSurvivor = oldItems.find(item => item.y + item.height > visibleOffset && nextKeys.has(item.key));
|
|
1814
|
+
const anchor = visibleSurvivor;
|
|
1815
|
+
this.cancelStructuralAnimation();
|
|
1816
|
+
this.structuralScrollInterrupted = false;
|
|
1817
|
+
this.structuralAnchorStyles = {
|
|
1818
|
+
owner: owner.style.overflowAnchor,
|
|
1819
|
+
content: this.content.style.overflowAnchor
|
|
1820
|
+
};
|
|
1821
|
+
owner.style.overflowAnchor = 'none';
|
|
1822
|
+
this.content.style.overflowAnchor = 'none';
|
|
1823
|
+
this.structuralContentOverflow = this.content.style.overflow;
|
|
1824
|
+
if (prefixTailChange) this.content.style.overflow = 'clip';
|
|
1825
|
+
this.structuralRenderedHeight = startHeight;
|
|
1826
|
+
this.structuralFooterFromHeight = oldFooterHeight;
|
|
1827
|
+
this.structuralFooterCompensation = Math.max(0, footerDifference);
|
|
1828
|
+
this.structuralFooterExpansion = Math.max(0, -footerDifference);
|
|
1829
|
+
this.structuralProgress = 0;
|
|
1830
|
+
this.reactFooterHeight = nextFooterHeight;
|
|
1831
|
+
this.structuralFooterElement = this.reactFooterElement() ?? undefined;
|
|
1832
|
+
if (this.structuralFooterElement) {
|
|
1833
|
+
const style = this.structuralFooterElement.style;
|
|
1834
|
+
this.structuralFooterStyles = {
|
|
1835
|
+
marginBottom: style.marginBottom,
|
|
1836
|
+
transform: style.transform,
|
|
1837
|
+
clipPath: style.clipPath
|
|
1838
|
+
};
|
|
1839
|
+
this.applyStructuralFooterVisual(0);
|
|
1840
|
+
}
|
|
1841
|
+
this.setSnapshot(next);
|
|
1842
|
+
const newHeight = this.layout.contentHeight;
|
|
1843
|
+
this.structuralTargetHeight = newHeight;
|
|
1844
|
+
const stablePrefixGeometry = prefixTailChange && oldItems.length === oldRows.length && this.layout.items.length === nextRows.length && oldItems.slice(0, prefixCount).every((item, index) => {
|
|
1845
|
+
const nextItem = this.layout.items[index];
|
|
1846
|
+
return nextItem?.y === item.y && nextItem?.height === item.height && nextItem?.width === item.width;
|
|
1847
|
+
});
|
|
1848
|
+
if (!stablePrefixGeometry) {
|
|
1849
|
+
this.content.style.overflow = this.structuralContentOverflow;
|
|
1850
|
+
this.structuralContentOverflow = undefined;
|
|
1851
|
+
} else {
|
|
1852
|
+
this.structuralPrefixTransition = true;
|
|
1853
|
+
}
|
|
1854
|
+
if (stablePrefixGeometry && nextRows.length < oldRows.length) {
|
|
1855
|
+
const layer = createElement(this.document, 'div', 'ok-native-list-structural-tail');
|
|
1856
|
+
layer.setAttribute('aria-hidden', 'true');
|
|
1857
|
+
layer.setAttribute('inert', '');
|
|
1858
|
+
Object.assign(layer.style, {
|
|
1859
|
+
position: 'absolute',
|
|
1860
|
+
inset: '0',
|
|
1861
|
+
pointerEvents: 'none'
|
|
1862
|
+
});
|
|
1863
|
+
this.content.append(layer);
|
|
1864
|
+
this.structuralTail = {
|
|
1865
|
+
snapshot: oldSnapshot,
|
|
1866
|
+
rows: oldRows,
|
|
1867
|
+
layout: oldLayout,
|
|
1868
|
+
firstIndex: prefixCount,
|
|
1869
|
+
layer,
|
|
1870
|
+
mounted: new Map()
|
|
1871
|
+
};
|
|
1872
|
+
this.updateStructuralTailWindow();
|
|
1873
|
+
}
|
|
1874
|
+
const nextAnchor = anchor && this.layout.items.find(item => item.key === anchor.key);
|
|
1875
|
+
const delta = nextAnchor && anchor ? nextAnchor.y - anchor.y : 0;
|
|
1876
|
+
let finalScrollHeight = oldScrollHeight + newHeight - oldHeight;
|
|
1877
|
+
if (stablePrefixGeometry && this.externalScrollHost) {
|
|
1878
|
+
const beforeMeasure = owner.scrollTop;
|
|
1879
|
+
const tailLayer = this.structuralTail?.layer;
|
|
1880
|
+
if (tailLayer) tailLayer.style.display = 'none';
|
|
1881
|
+
this.writeStructuralHeight(newHeight);
|
|
1882
|
+
this.applyStructuralFooterVisual(1);
|
|
1883
|
+
finalScrollHeight = owner.scrollHeight;
|
|
1884
|
+
this.writeStructuralHeight(startHeight);
|
|
1885
|
+
this.applyStructuralFooterVisual(0);
|
|
1886
|
+
if (tailLayer) tailLayer.style.display = '';
|
|
1887
|
+
owner.scrollTop = beforeMeasure;
|
|
1888
|
+
}
|
|
1889
|
+
const finalMaxOffset = Math.max(0, finalScrollHeight - owner.clientHeight);
|
|
1890
|
+
let targetOffset = Math.max(0, Math.min(oldOffset + delta, finalMaxOffset));
|
|
1891
|
+
if (!visibleSurvivor && transition.anchorKey && !(stablePrefixGeometry && nextRows.length > oldRows.length)) {
|
|
1892
|
+
const fallback = this.layout.items.find(item => item.key === transition.anchorKey);
|
|
1893
|
+
if (fallback) {
|
|
1894
|
+
const pagerStickyInset = Number.parseFloat(this.externalScrollHost?.style.getPropertyValue('--ok-collapsible-pager-sticky-inset') ?? '');
|
|
1895
|
+
const effectiveStickyInset = Math.max(this.externalStickyInset, Number.isFinite(pagerStickyInset) ? pagerStickyInset : 0);
|
|
1896
|
+
const fallbackTop = this.externalScrollHost ? this.externalGeometry().origin + fallback.y - effectiveStickyInset : resolveWebCollapsiblePagerRawOffset(Math.max(0, fallback.y - this.collapsiblePagerInsets().sticky), this.collapsiblePagerInsets().header);
|
|
1897
|
+
if (stablePrefixGeometry && this.externalScrollHost && this.reactFooterHeight > 0) {
|
|
1898
|
+
const footerTop = this.externalGeometry().origin + newHeight;
|
|
1899
|
+
const footerStart = Math.max(0, footerTop + this.reactFooterHeight - owner.clientHeight);
|
|
1900
|
+
const footerEnd = Math.max(0, footerTop - effectiveStickyInset);
|
|
1901
|
+
const nearestVisibleOffset = footerStart <= footerEnd ? Math.max(footerStart, Math.min(oldOffset, footerEnd)) : footerEnd;
|
|
1902
|
+
targetOffset = Math.max(0, Math.min(nearestVisibleOffset, finalMaxOffset));
|
|
1903
|
+
} else {
|
|
1904
|
+
targetOffset = Math.min(targetOffset, Math.max(0, fallbackTop));
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
const duration = transition.durationMs ?? 220;
|
|
1909
|
+
const easing = 'cubic-bezier(0.42, 0, 0.58, 1)';
|
|
1910
|
+
this.mounted.forEach((element, index) => {
|
|
1911
|
+
const row = this.rows[index];
|
|
1912
|
+
const previousTop = row && oldPositions.get(row.key);
|
|
1913
|
+
if (previousTop === undefined || typeof element.animate !== 'function') return;
|
|
1914
|
+
const offset = previousTop - element.getBoundingClientRect().top;
|
|
1915
|
+
if (Math.abs(offset) < 0.5) return;
|
|
1916
|
+
this.structuralAnimations.push(element.animate([{
|
|
1917
|
+
transform: `translateY(${offset}px)`
|
|
1918
|
+
}, {
|
|
1919
|
+
transform: 'translateY(0)'
|
|
1920
|
+
}], {
|
|
1921
|
+
duration,
|
|
1922
|
+
easing
|
|
1923
|
+
}));
|
|
1924
|
+
});
|
|
1925
|
+
const startedAt = this.document.defaultView?.performance.now() ?? Date.now();
|
|
1926
|
+
const revision = this.structuralRevision;
|
|
1927
|
+
const finish = () => {
|
|
1928
|
+
if (this.destroyed || revision !== this.structuralRevision) return;
|
|
1929
|
+
const ownsScroll = !this.structuralScrollInterrupted;
|
|
1930
|
+
this.cancelStructuralAnimation();
|
|
1931
|
+
this.recomputeLayout();
|
|
1932
|
+
if (stablePrefixGeometry && ownsScroll) {
|
|
1933
|
+
owner.scrollTop = Math.max(0, Math.min(targetOffset, owner.scrollHeight - owner.clientHeight));
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
const step = time => {
|
|
1937
|
+
if (this.destroyed || revision !== this.structuralRevision) return;
|
|
1938
|
+
if (this.structuralPrefixTransition && this.document.defaultView?.matchMedia?.('(prefers-reduced-motion: reduce)').matches) {
|
|
1939
|
+
finish();
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
const progress = Math.min(1, (time - startedAt) / duration);
|
|
1943
|
+
const eased = progress * progress * (3 - 2 * progress);
|
|
1944
|
+
this.structuralProgress = eased;
|
|
1945
|
+
const renderedHeight = oldHeight + ((this.structuralTargetHeight ?? newHeight) - oldHeight) * eased + this.structuralFooterCompensation * (1 - eased);
|
|
1946
|
+
this.structuralRenderedHeight = renderedHeight;
|
|
1947
|
+
this.writeStructuralHeight(renderedHeight);
|
|
1948
|
+
this.applyStructuralFooterVisual(eased);
|
|
1949
|
+
if (!this.structuralScrollInterrupted) owner.scrollTop = oldOffset + (targetOffset - oldOffset) * eased;
|
|
1950
|
+
this.externalGeometryCache = undefined;
|
|
1951
|
+
this.updateStructuralTailWindow();
|
|
1952
|
+
if (progress < 1) this.structuralFrame = this.document.defaultView?.requestAnimationFrame(step);
|
|
1953
|
+
};
|
|
1954
|
+
this.structuralFrame = this.document.defaultView?.requestAnimationFrame(step);
|
|
1955
|
+
this.structuralFinish = this.document.defaultView?.setTimeout(finish, duration + 40);
|
|
1527
1956
|
}
|
|
1528
1957
|
currentContentHeight() {
|
|
1529
1958
|
return this.layout.contentHeight;
|
|
@@ -1696,6 +2125,8 @@ export class NativeListWebEngine {
|
|
|
1696
2125
|
}
|
|
1697
2126
|
destroy() {
|
|
1698
2127
|
if (this.destroyed) return;
|
|
2128
|
+
this.cancelStructuralAnimation();
|
|
2129
|
+
this.pressedHelpElement = undefined;
|
|
1699
2130
|
this.invalidateActionAnchor('destroy');
|
|
1700
2131
|
this.destroyed = true;
|
|
1701
2132
|
if (this.frameHandle !== undefined) this.cancelFrame(this.frameHandle);
|
|
@@ -1708,6 +2139,7 @@ export class NativeListWebEngine {
|
|
|
1708
2139
|
this.document.defaultView?.removeEventListener('resize', this.handleWindowResize);
|
|
1709
2140
|
this.pendingScroll = undefined;
|
|
1710
2141
|
(this.externalScrollHost ?? this.viewport).removeEventListener('ok-collapsible-pager-cancel-scroll-command', this.handlePagerScrollCommandCancel);
|
|
2142
|
+
for (const event of ['wheel', 'pointerdown', 'touchstart']) (this.externalScrollHost ?? this.viewport).removeEventListener(event, this.handleStructuralUserScroll);
|
|
1711
2143
|
this.viewport.removeEventListener('scroll', this.handleScroll);
|
|
1712
2144
|
(this.externalScrollHost ?? this.viewport).removeEventListener('ok-collapsible-pager-insets-changed', this.handleCollapsiblePagerInsetsChanged);
|
|
1713
2145
|
this.root.removeEventListener('click', this.handleClick);
|
|
@@ -1719,6 +2151,7 @@ export class NativeListWebEngine {
|
|
|
1719
2151
|
this.root.removeEventListener('pointerup', this.handleMarketPointerEnd);
|
|
1720
2152
|
this.root.removeEventListener('pointercancel', this.handleMarketPointerEnd);
|
|
1721
2153
|
this.root.removeEventListener('pointerover', this.handleTitlePointerOver);
|
|
2154
|
+
this.root.removeEventListener('pointerdown', this.handleIconHelpPointerDown);
|
|
1722
2155
|
this.root.removeEventListener('focusin', this.handleTitlePointerOver);
|
|
1723
2156
|
this.root.removeEventListener('focusout', this.handleTitlePointerOut);
|
|
1724
2157
|
this.root.removeEventListener('pointerout', this.handleTitlePointerOut);
|
|
@@ -1757,6 +2190,7 @@ export class NativeListWebEngine {
|
|
|
1757
2190
|
}
|
|
1758
2191
|
setSnapshot(snapshot, selectedKeys) {
|
|
1759
2192
|
this.cancelMarketPointer();
|
|
2193
|
+
this.pressedHelpElement = undefined;
|
|
1760
2194
|
this.measuredRendererHeights.clear();
|
|
1761
2195
|
this.snapshot = snapshot;
|
|
1762
2196
|
this.rows = effectiveRows(snapshot);
|
|
@@ -1774,6 +2208,7 @@ export class NativeListWebEngine {
|
|
|
1774
2208
|
'--nl-row': theme.rowBackground,
|
|
1775
2209
|
'--nl-selected': theme.rowSelectedBackground,
|
|
1776
2210
|
'--nl-pressed': theme.rowPressedBackground,
|
|
2211
|
+
'--nl-hover': theme.rowHoverBackground ?? theme.rowPressedBackground,
|
|
1777
2212
|
'--nl-subdued': theme.subduedBackground,
|
|
1778
2213
|
'--nl-strong': theme.strongBackground,
|
|
1779
2214
|
'--nl-image-fallback-background': theme.imageFallbackBackground ?? 'transparent',
|
|
@@ -1790,6 +2225,7 @@ export class NativeListWebEngine {
|
|
|
1790
2225
|
'--nl-separator': theme.separator,
|
|
1791
2226
|
'--nl-accent': theme.accent,
|
|
1792
2227
|
'--nl-positive': theme.positive,
|
|
2228
|
+
'--nl-success-background': theme.successBackground,
|
|
1793
2229
|
'--nl-negative': theme.negative,
|
|
1794
2230
|
'--nl-critical': theme.criticalBackground,
|
|
1795
2231
|
'--nl-inverse': theme.inverseBackground,
|
|
@@ -1850,10 +2286,24 @@ export class NativeListWebEngine {
|
|
|
1850
2286
|
}
|
|
1851
2287
|
recomputeLayout = () => {
|
|
1852
2288
|
if (this.destroyed) return;
|
|
2289
|
+
if (this.structuralPrefixTransition && this.lastViewportWidth > 0 && this.viewport.clientWidth > 0 && this.viewport.clientWidth !== this.lastViewportWidth) this.cancelStructuralAnimation();
|
|
2290
|
+
if (this.structuralRenderedHeight === undefined) this.reactFooterHeight = this.readReactFooterHeight();else {
|
|
2291
|
+
const nextFooterHeight = this.readReactFooterHeight();
|
|
2292
|
+
const footerDelta = this.reactFooterHeight - nextFooterHeight;
|
|
2293
|
+
if (footerDelta !== 0) {
|
|
2294
|
+
this.reactFooterHeight = nextFooterHeight;
|
|
2295
|
+
const priorCompensation = this.structuralFooterCompensation;
|
|
2296
|
+
const difference = this.structuralFooterFromHeight - nextFooterHeight;
|
|
2297
|
+
this.structuralFooterCompensation = Math.max(0, difference);
|
|
2298
|
+
this.structuralFooterExpansion = Math.max(0, -difference);
|
|
2299
|
+
this.structuralRenderedHeight += (this.structuralFooterCompensation - priorCompensation) * (1 - this.structuralProgress);
|
|
2300
|
+
this.applyStructuralFooterVisual(this.structuralProgress);
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
1853
2303
|
const cachedWidth = this.lastViewportWidth;
|
|
1854
2304
|
const cachedHeight = this.lastViewportHeight;
|
|
1855
2305
|
const precomputedLayout = this.externalScrollHost && cachedWidth > 0 && cachedHeight > 0 ? this.computeLayout(cachedWidth, cachedHeight) : undefined;
|
|
1856
|
-
if (precomputedLayout) {
|
|
2306
|
+
if (precomputedLayout && this.structuralRenderedHeight === undefined) {
|
|
1857
2307
|
// Commit appended row extent before measuring React-owned slot changes.
|
|
1858
2308
|
this.writeExternalHeight(Math.max(this.layout.contentHeight, precomputedLayout.contentHeight));
|
|
1859
2309
|
}
|
|
@@ -1883,11 +2333,13 @@ export class NativeListWebEngine {
|
|
|
1883
2333
|
const previousHorizontal = this.layout.horizontal;
|
|
1884
2334
|
this.layout = precomputedLayout && viewportWidth === cachedWidth && viewportHeight === cachedHeight ? precomputedLayout : this.computeLayout(viewportWidth, viewportHeight);
|
|
1885
2335
|
this.content.style.width = String(this.layout.contentWidth) + 'px';
|
|
1886
|
-
this.
|
|
2336
|
+
const renderedHeight = this.structuralRenderedHeight ?? this.layout.contentHeight;
|
|
2337
|
+
this.content.style.height = String(renderedHeight) + 'px';
|
|
1887
2338
|
if (this.externalScrollHost) {
|
|
1888
|
-
this.writeExternalHeight(
|
|
2339
|
+
this.writeExternalHeight(renderedHeight);
|
|
1889
2340
|
this.externalGeometryCache = undefined;
|
|
1890
2341
|
}
|
|
2342
|
+
if (this.structuralRenderedHeight !== undefined) this.structuralTargetHeight = this.layout.contentHeight;
|
|
1891
2343
|
this.renderSectionIndex(this.viewport.clientHeight <= 0 ? DEFAULT_VIEWPORT_HEIGHT : Math.max(1, viewportHeight), stickyInset);
|
|
1892
2344
|
if (previousHorizontal !== this.layout.horizontal) {
|
|
1893
2345
|
this.viewport.scrollLeft = 0;
|
|
@@ -1995,6 +2447,7 @@ export class NativeListWebEngine {
|
|
|
1995
2447
|
}
|
|
1996
2448
|
this.updateVisibleSelection();
|
|
1997
2449
|
this.updateVisibleState();
|
|
2450
|
+
this.updateStructuralTailWindow();
|
|
1998
2451
|
}
|
|
1999
2452
|
positionElement(element, item) {
|
|
2000
2453
|
element.style.transform = 'translate3d(' + String(item.x) + 'px,' + String(item.y) + 'px,0)';
|
|
@@ -2040,7 +2493,7 @@ export class NativeListWebEngine {
|
|
|
2040
2493
|
const body = reusableBody ?? createRowBody(context, row);
|
|
2041
2494
|
if (reusableBody) {
|
|
2042
2495
|
resetRowContainerStyle(body);
|
|
2043
|
-
registered.bind(body, rendererPrimitives(context));
|
|
2496
|
+
registered.bind(body, rendererPrimitives(context, Boolean(row.disabled)));
|
|
2044
2497
|
}
|
|
2045
2498
|
// OneKey patch: explicit selector fields preserve original page geometry.
|
|
2046
2499
|
element.style.contain = row.backgroundFullWidth ? 'layout style' : '';
|
|
@@ -2522,6 +2975,7 @@ export class NativeListWebEngine {
|
|
|
2522
2975
|
return anchor.actionElement.isConnected && anchor.rowElement.isConnected && anchor.rowElement.contains(anchor.actionElement) && anchor.rowElement.dataset.nativeListBindingEpoch === anchor.bindingEpoch;
|
|
2523
2976
|
}
|
|
2524
2977
|
invalidateActionAnchorForElement(element) {
|
|
2978
|
+
if (this.pressedHelpElement && element.contains(this.pressedHelpElement)) this.pressedHelpElement = undefined;
|
|
2525
2979
|
const anchor = this.actionAnchor;
|
|
2526
2980
|
if (anchor && (element === anchor.rowElement || element.contains(anchor.actionElement))) {
|
|
2527
2981
|
this.invalidateActionAnchor('rebind');
|
|
@@ -2594,9 +3048,9 @@ export class NativeListWebEngine {
|
|
|
2594
3048
|
if (event.target.closest('[data-native-list-action]')) return;
|
|
2595
3049
|
const rowElement = event.target.closest('[data-native-list-row-key]');
|
|
2596
3050
|
const row = this.rowAtElement(rowElement);
|
|
2597
|
-
if (row?.type !== 'market' || !isRowPressEnabled(row)) return;
|
|
3051
|
+
if (row?.type !== 'market' && row?.type !== 'identity' || !isRowPressEnabled(row)) return;
|
|
2598
3052
|
this.cancelMarketPointer();
|
|
2599
|
-
if (row.pressInActionKey) this.emitRowAction(row, row.pressInActionKey, rowElement ?? undefined, rowElement ?? undefined);
|
|
3053
|
+
if (row.type === 'market' && row.pressInActionKey) this.emitRowAction(row, row.pressInActionKey, rowElement ?? undefined, rowElement ?? undefined);
|
|
2600
3054
|
if (!row.longPressActionKey || !rowElement) return;
|
|
2601
3055
|
markActionAnchorSource(rowElement, 'row');
|
|
2602
3056
|
const bindingEpoch = rowElement.dataset.nativeListBindingEpoch;
|
|
@@ -2605,7 +3059,7 @@ export class NativeListWebEngine {
|
|
|
2605
3059
|
if (!current || current.pointerId !== event.pointerId) return;
|
|
2606
3060
|
const currentRow = this.rowAtElement(rowElement);
|
|
2607
3061
|
this.marketPointer = undefined;
|
|
2608
|
-
if (!rowElement.isConnected || rowElement.dataset.nativeListBindingEpoch !== bindingEpoch || currentRow?.key !== row.key || currentRow.type !== 'market' || !isRowPressEnabled(currentRow) || !currentRow.longPressActionKey) return;
|
|
3062
|
+
if (!rowElement.isConnected || rowElement.dataset.nativeListBindingEpoch !== bindingEpoch || currentRow?.key !== row.key || currentRow.type !== 'market' && currentRow.type !== 'identity' || !isRowPressEnabled(currentRow) || !currentRow.longPressActionKey) return;
|
|
2609
3063
|
this.marketLongPressFired = true;
|
|
2610
3064
|
this.emitRowAction(currentRow, currentRow.longPressActionKey, rowElement, rowElement, {
|
|
2611
3065
|
x: event.clientX,
|
|
@@ -2616,7 +3070,7 @@ export class NativeListWebEngine {
|
|
|
2616
3070
|
this.marketPointer = {
|
|
2617
3071
|
pointerId: event.pointerId,
|
|
2618
3072
|
pointerType: event.pointerType,
|
|
2619
|
-
compact: !row.webTable,
|
|
3073
|
+
compact: row.type === 'identity' || !row.webTable,
|
|
2620
3074
|
rowKey: row.key,
|
|
2621
3075
|
startX: event.clientX,
|
|
2622
3076
|
startY: event.clientY,
|
|
@@ -2652,7 +3106,14 @@ export class NativeListWebEngine {
|
|
|
2652
3106
|
if (!(target instanceof Element)) return;
|
|
2653
3107
|
const action = target.closest('[data-native-list-hover-action]');
|
|
2654
3108
|
if (!action || event.relatedTarget instanceof Node && action.contains(event.relatedTarget)) return;
|
|
3109
|
+
if (action.dataset.nativeListIconHelp === 'true') {
|
|
3110
|
+
if (event.type === 'pointerover' && event.pointerType === 'touch') return;
|
|
3111
|
+
if (this.pressedHelpElement === action) return;
|
|
3112
|
+
}
|
|
2655
3113
|
if (action.classList.contains('ok-native-list-market-subtitle-prefix') && action.scrollWidth <= action.clientWidth + 1) return;
|
|
3114
|
+
this.emitHoverAction(action);
|
|
3115
|
+
};
|
|
3116
|
+
emitHoverAction(action) {
|
|
2656
3117
|
const rowElement = action.closest('[data-native-list-row-key]');
|
|
2657
3118
|
const row = this.rowAtElement(rowElement);
|
|
2658
3119
|
const memberKey = action.closest('[data-native-list-group-member-key]')?.dataset.nativeListGroupMemberKey;
|
|
@@ -2661,12 +3122,26 @@ export class NativeListWebEngine {
|
|
|
2661
3122
|
// Legacy Web: hover checks only the resolved source (the member for a
|
|
2662
3123
|
// WalletGroup), not the enclosing row's `disabled`.
|
|
2663
3124
|
if (sourceRow && !sourceRow.disabled && actionKey) this.emitRowAction(sourceRow, actionKey, action, rowElement ?? undefined);
|
|
3125
|
+
}
|
|
3126
|
+
handleIconHelpPointerDown = event => {
|
|
3127
|
+
const target = event.target;
|
|
3128
|
+
if (!(target instanceof Element)) return;
|
|
3129
|
+
const action = target.closest('[data-native-list-icon-help="true"]');
|
|
3130
|
+
if (!action) return;
|
|
3131
|
+
if (event.pointerType === 'touch') {
|
|
3132
|
+
if (this.actionAnchor?.actionElement === action && this.actionAnchor.open) this.invalidateActionAnchor('pointerLeave');else this.emitHoverAction(action);
|
|
3133
|
+
} else {
|
|
3134
|
+
this.pressedHelpElement = action;
|
|
3135
|
+
if (this.actionAnchor?.actionElement === action) this.invalidateActionAnchor('pointerLeave');
|
|
3136
|
+
}
|
|
2664
3137
|
};
|
|
2665
3138
|
handleTitlePointerOut = event => {
|
|
2666
3139
|
const target = event.target;
|
|
2667
3140
|
if (!(target instanceof Element)) return;
|
|
2668
3141
|
const action = target.closest('[data-native-list-hover-action]');
|
|
2669
3142
|
if (!action || event.relatedTarget instanceof Node && action.contains(event.relatedTarget)) return;
|
|
3143
|
+
if (action.dataset.nativeListIconHelp === 'true' && event.type === 'pointerout' && event.pointerType === 'touch') return;
|
|
3144
|
+
if (event.type === 'pointerout' && this.pressedHelpElement === action) this.pressedHelpElement = undefined;
|
|
2670
3145
|
if (this.actionAnchor?.actionElement === action) this.invalidateActionAnchor('pointerLeave');
|
|
2671
3146
|
};
|
|
2672
3147
|
handleClick = event => {
|
|
@@ -2678,6 +3153,11 @@ export class NativeListWebEngine {
|
|
|
2678
3153
|
}
|
|
2679
3154
|
const target = event.target;
|
|
2680
3155
|
if (!(target instanceof Element)) return;
|
|
3156
|
+
if (target.closest('[data-native-list-icon-help="true"]')) {
|
|
3157
|
+
event.preventDefault();
|
|
3158
|
+
event.stopPropagation();
|
|
3159
|
+
return;
|
|
3160
|
+
}
|
|
2681
3161
|
const rowElement = target.closest('[data-native-list-row-key]');
|
|
2682
3162
|
const row = this.rowAtElement(rowElement);
|
|
2683
3163
|
if (!row || row.disabled) return;
|
|
@@ -2689,6 +3169,8 @@ export class NativeListWebEngine {
|
|
|
2689
3169
|
// member press is blocked by `isRowPressEnabled` in `handleRowPress`.
|
|
2690
3170
|
const action = target.closest('[data-native-list-action]');
|
|
2691
3171
|
if (action) {
|
|
3172
|
+
if (action.tagName === 'BUTTON' && action.hasAttribute('disabled')) return;
|
|
3173
|
+
if (action.classList.contains('ok-native-list-trailing-button')) event.stopPropagation();
|
|
2692
3174
|
const scope = action.dataset.selectionScope;
|
|
2693
3175
|
if (scope === 'row') this.activateSelection({
|
|
2694
3176
|
scope: 'row'
|
|
@@ -2703,6 +3185,11 @@ export class NativeListWebEngine {
|
|
|
2703
3185
|
this.handleRowPress(sourceRow, rowElement ?? undefined, memberElement ?? rowElement ?? undefined);
|
|
2704
3186
|
};
|
|
2705
3187
|
handleKeyDown = event => {
|
|
3188
|
+
if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && event.target.matches('[role="button"][data-native-list-hover-action]')) {
|
|
3189
|
+
event.preventDefault();
|
|
3190
|
+
if (this.actionAnchor?.actionElement !== event.target || !this.actionAnchor.open) this.emitHoverAction(event.target);
|
|
3191
|
+
return;
|
|
3192
|
+
}
|
|
2706
3193
|
// OneKey patch: non-button title help supports keyboard activation.
|
|
2707
3194
|
if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && event.target.matches('[role="button"][data-native-list-action]')) {
|
|
2708
3195
|
event.preventDefault();
|
|
@@ -2804,6 +3291,7 @@ export class NativeListWebEngine {
|
|
|
2804
3291
|
};
|
|
2805
3292
|
handleScroll = () => {
|
|
2806
3293
|
this.externalGeometryCache = undefined;
|
|
3294
|
+
this.pressedHelpElement = undefined;
|
|
2807
3295
|
this.cancelMarketPointer();
|
|
2808
3296
|
this.invalidateActionAnchor('scroll');
|
|
2809
3297
|
this.scheduleFrame();
|