adp-web-components 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{add-icon-BklgM02f.js → add-icon-r-uugVfd.js} +1 -1
- package/dist/cjs/{app-globals-XGpRBTr6.js → app-globals-BoQSQFz7.js} +1 -1
- package/dist/cjs/{arrow-up-icon-BLo1aQC2.js → arrow-up-icon-BfnEuyBs.js} +1 -1
- package/dist/cjs/branch-date-dropdown_17.cjs.entry.js +51 -45
- package/dist/cjs/{calendar-days-icon-Cf14ROXV.js → calendar-days-icon-CDsv0_-r.js} +1 -1
- package/dist/cjs/{check-icon-DaQxP2EY.js → check-icon-BNxUv6rL.js} +1 -1
- package/dist/cjs/clock-DsYk5zt3.js +30 -0
- package/dist/cjs/dead-stock-lookup_3.cjs.entry.js +10 -9
- package/dist/cjs/{decode-time-offset-DOUImlif.js → decode-time-offset-CcpzHLhD.js} +10 -2
- package/dist/cjs/flexible-container.cjs.entry.js +2 -2
- package/dist/cjs/form-checkbox.cjs.entry.js +3 -3
- package/dist/cjs/form-date-picker.cjs.entry.js +25 -19
- package/dist/cjs/{form-error-message-BtLdHgxO.js → form-error-message-DdEeLvoD.js} +1 -1
- package/dist/cjs/{form-input-label-B4lkF89K.js → form-input-label-U5kCHkJl.js} +1 -1
- package/dist/cjs/form-input_7.cjs.entry.js +13 -13
- package/dist/cjs/form-switch.cjs.entry.js +3 -3
- package/dist/cjs/form-time-picker.cjs.entry.js +4 -4
- package/dist/cjs/{functions-gb1i8Hkl.js → functions-Bz2-CHK9.js} +5 -4
- package/dist/cjs/general-form.cjs.entry.js +11 -10
- package/dist/cjs/general-inquiry-form.cjs.entry.js +11 -10
- package/dist/cjs/{get-language-from-url-DwOt9DVH.js → get-language-from-url-CivsCH6R.js} +1 -1
- package/dist/cjs/{get-local-language-CZeC0BN9.js → get-local-language-BBdU8ppU.js} +2 -2
- package/dist/cjs/get-mock-files-VecUdVE7.js +61 -0
- package/dist/cjs/{index-BdHAYIvO.js → index-BXyIPFx-.js} +3 -0
- package/dist/cjs/information-table.cjs.entry.js +3 -3
- package/dist/cjs/{loader-icon-aY56OHXW.js → loader-icon-BkPuyYFm.js} +1 -1
- package/dist/cjs/loader.cjs.js +3 -3
- package/dist/cjs/loading-spinner.cjs.entry.js +1 -1
- package/dist/cjs/manufacturer-part-lookup.cjs.entry.js +4 -4
- package/dist/cjs/{mappers-DnWgECCv.js → mappers-D-v6mh0y.js} +10 -8
- package/dist/cjs/{material-card-D1UQcy6U.js → material-card-mXTu16Ev.js} +1 -1
- package/dist/cjs/mock-assets-Dio-Q8Yd.js +13 -0
- package/dist/cjs/part-lookup.cjs.entry.js +4 -4
- package/dist/cjs/{qr-code-scan-CtKK6wLL.js → qr-code-scan-BH1paDvW.js} +1 -1
- package/dist/cjs/{reveal-below-CyYolTYX.js → reveal-below-7_fSN_sU.js} +1 -1
- package/dist/cjs/service-booking-form.cjs.entry.js +11 -10
- package/dist/cjs/shift-accordion.cjs.entry.js +1 -1
- package/dist/cjs/shift-checkbox.cjs.entry.js +3 -3
- package/dist/cjs/shift-components.cjs.js +3 -3
- package/dist/cjs/shift-slider.cjs.entry.js +1 -1
- package/dist/cjs/shift-switch.cjs.entry.js +2 -2
- package/dist/cjs/shift-tab-content.cjs.entry.js +2 -2
- package/dist/cjs/shift-tabs_2.cjs.entry.js +7 -7
- package/dist/cjs/ssc-lookup-form.cjs.entry.js +11 -10
- package/dist/cjs/test-drive-form.cjs.entry.js +11 -10
- package/dist/cjs/{triangle-alert-CTvU1eGY.js → triangle-alert-C_xSEmRy.js} +1 -1
- package/dist/cjs/vehicle-accessories_8.cjs.entry.js +72 -44
- package/dist/cjs/{vehicle-info-layout-CRpL8UMY.js → vehicle-info-layout-CjYyiBEq.js} +1 -1
- package/dist/cjs/vehicle-lookup.cjs.entry.js +21 -17
- package/dist/cjs/vehicle-quotation-form.cjs.entry.js +8 -7
- package/dist/cjs/{white-loader-CveXuRsH.js → white-loader-CH2BrmT6.js} +1 -1
- package/dist/collection/components/components/empty.css +1 -1
- package/dist/collection/components/components/flexible-container.css +1 -1
- package/dist/collection/components/components/information-table.css +1 -1
- package/dist/collection/components/components/shift-portal.css +1 -1
- package/dist/collection/components/components/shift-select-dropdown.css +1 -1
- package/dist/collection/components/components/shift-select.css +1 -1
- package/dist/collection/components/components/shift-tab-content.css +1 -1
- package/dist/collection/components/components/shift-tabs.css +1 -1
- package/dist/collection/components/form-elements/branch-date-picker.js +30 -8
- package/dist/collection/components/form-elements/branch-slot-dropdown.css +1 -1
- package/dist/collection/components/form-elements/branch-slot-picker.js +29 -6
- package/dist/collection/components/form-elements/form-date-picker-legacy.js +40 -15
- package/dist/collection/components/form-elements/form-inputs.css +1 -1
- package/dist/collection/components/form-elements/form-picker-input.js +27 -7
- package/dist/collection/components/form-elements/form-structure.js +20 -1
- package/dist/collection/components/forms/defaults/mappers.js +6 -4
- package/dist/collection/components/forms/general-form.js +21 -2
- package/dist/collection/components/forms/general-inquiry.js +21 -2
- package/dist/collection/components/forms/service-booking.js +21 -2
- package/dist/collection/components/forms/ssc-lookup.js +21 -2
- package/dist/collection/components/forms/test-drive.js +21 -2
- package/dist/collection/components/forms/vehicle-quotation.js +21 -2
- package/dist/collection/components/part-lookup/dead-stock-lookup.css +1 -1
- package/dist/collection/components/part-lookup/distributor-lookup.css +1 -1
- package/dist/collection/components/part-lookup/manufacturer-lookup.css +1 -1
- package/dist/collection/components/part-lookup/manufacturer-part-lookup.css +1 -1
- package/dist/collection/components/part-lookup/part-lookup.css +1 -1
- package/dist/collection/components/vehicle-lookup/components/CoverageTimeline.js +2 -2
- package/dist/collection/components/vehicle-lookup/vehicle-accessories.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-accessories.js +21 -2
- package/dist/collection/components/vehicle-lookup/vehicle-claimable-items.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-claimable-items.js +24 -5
- package/dist/collection/components/vehicle-lookup/vehicle-item-claim-form.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-lookup.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-lookup.js +61 -12
- package/dist/collection/components/vehicle-lookup/vehicle-paint-thickness.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-paint-thickness.js +19 -0
- package/dist/collection/components/vehicle-lookup/vehicle-sale-information.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-sale-information.js +21 -2
- package/dist/collection/components/vehicle-lookup/vehicle-service-history.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-service-history.js +20 -1
- package/dist/collection/components/vehicle-lookup/vehicle-specification.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-specification.js +20 -1
- package/dist/collection/components/vehicle-lookup/vehicle-ssc.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-ssc.js +57 -12
- package/dist/collection/components/vehicle-lookup/vehicle-warranty-timeline.css +1 -1
- package/dist/collection/components/vehicle-lookup/vehicle-warranty-timeline.js +20 -1
- package/dist/collection/features/form-hook/functions.js +2 -1
- package/dist/collection/features/form-hook/render-structure.js +1 -1
- package/dist/collection/features/mocks/data/assets/accessories/accessory.svg +10 -0
- package/dist/collection/features/mocks/data/assets/accessories/floor-mats.svg +10 -0
- package/dist/collection/features/mocks/data/assets/accessories/mud-guards.svg +11 -0
- package/dist/collection/features/mocks/data/assets/accessories/roof-rack.svg +11 -0
- package/dist/collection/features/mocks/data/assets/accessories/roof-rails.svg +11 -0
- package/dist/collection/features/mocks/data/assets/accessories/side-steps.svg +11 -0
- package/dist/collection/features/mocks/data/assets/accessories/tow-bar.svg +12 -0
- package/dist/collection/features/mocks/data/assets/badges/badge-1.svg +5 -0
- package/dist/collection/features/mocks/data/assets/badges/badge-2.svg +5 -0
- package/dist/collection/features/mocks/data/assets/badges/badge-3.svg +5 -0
- package/dist/collection/features/mocks/data/assets/badges/badge-4.svg +5 -0
- package/dist/collection/features/mocks/data/assets/badges/badge-5.svg +5 -0
- package/dist/collection/features/mocks/data/assets/badges/badge-6.svg +5 -0
- package/dist/collection/features/mocks/data/assets/documents/service-invoice-qr.svg +18 -0
- package/dist/collection/features/mocks/data/assets/documents/signed-claim-document.svg +21 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/door-front-left-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/door-front-left.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/door-front-right-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/door-front-right.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/door-rear-left-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/door-rear-left.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/door-rear-right-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/door-rear-right.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/fender-front-left-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/fender-front-left.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/fender-front-right-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/fender-front-right.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/fender-rear-left-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/fender-rear-left.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/fender-rear-right-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/fender-rear-right.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/hood-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/hood.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/panel.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/roof-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/roof.svg +6 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/tail-gate-detail.svg +7 -0
- package/dist/collection/features/mocks/data/assets/paint-panels/tail-gate.svg +6 -0
- package/dist/collection/features/mocks/get-mock-files.js +19 -14
- package/dist/collection/features/mocks/index.js +1 -0
- package/dist/collection/features/mocks/mock-assets.js +33 -0
- package/dist/collection/features/vehicle-lookup-component/vehicle-lookup-api-integration.js +3 -1
- package/dist/collection/global/lib/clock.js +25 -0
- package/dist/collection/global/lib/decode-time-offset.js +9 -1
- package/dist/collection/templates/forms/docs-content/structure.js +1 -1
- package/dist/collection/templates/harness-connection.js +282 -0
- package/dist/collection/templates/harness-environment.js +31 -0
- package/dist/collection/templates/harness.js +610 -83
- package/dist/collection/templates/site-header.js +2 -2
- package/dist/components/branch-date-picker.js +1 -1
- package/dist/components/branch-slot-dropdown.js +1 -1
- package/dist/components/branch-slot-picker.js +1 -1
- package/dist/components/dead-stock-lookup.js +1 -1
- package/dist/components/distributor-lookup.js +1 -1
- package/dist/components/flexible-container.js +1 -1
- package/dist/components/form-checkbox.js +1 -1
- package/dist/components/form-date-picker.js +1 -1
- package/dist/components/form-file.js +1 -1
- package/dist/components/form-input-preview.js +1 -1
- package/dist/components/form-input.js +1 -1
- package/dist/components/form-phone-number.js +1 -1
- package/dist/components/form-picker-input.js +1 -1
- package/dist/components/form-select.js +1 -1
- package/dist/components/form-shadow-input.js +1 -1
- package/dist/components/form-stepper-control.js +1 -1
- package/dist/components/form-stepper-submit.js +1 -1
- package/dist/components/form-stepper.js +1 -1
- package/dist/components/form-structure-error.js +1 -1
- package/dist/components/form-structure.js +1 -1
- package/dist/components/form-submit.js +1 -1
- package/dist/components/form-switch.js +1 -1
- package/dist/components/form-text-area.js +1 -1
- package/dist/components/form-time-picker.js +1 -1
- package/dist/components/form-vin-input.js +1 -1
- package/dist/components/general-form.js +1 -1
- package/dist/components/general-inquiry-form.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/information-table.js +1 -1
- package/dist/components/manufacturer-lookup.js +1 -1
- package/dist/components/manufacturer-part-lookup.js +1 -1
- package/dist/components/{p-Ype8FNjy.js → p-3e83-if9.js} +1 -1
- package/dist/components/p-B3ztFt72.js +5 -0
- package/dist/components/p-B4PUnAtc.js +5 -0
- package/dist/components/{p-bVbnoz7C.js → p-B7OLLrcA.js} +1 -1
- package/dist/components/{p-d1WgLP9O.js → p-BEHSLtOA.js} +1 -1
- package/dist/components/{p-UFwS4oV2.js → p-B_EZX2Nj.js} +1 -1
- package/dist/components/{p-BAkLdLKZ.js → p-BcgJGb3U.js} +1 -1
- package/dist/components/p-BdxXAS3w.js +5 -0
- package/dist/components/{p-CebvOd8T.js → p-Bf7SK7BI.js} +1 -1
- package/dist/components/{p-BDOUh9fr.js → p-Bhy0nttE.js} +1 -1
- package/dist/components/p-BjDxP9Ar.js +5 -0
- package/dist/components/{p-DxRQkoRz.js → p-C-R7Zf1I.js} +1 -1
- package/dist/components/{p-CT-MbmyW.js → p-C1-ek7if.js} +1 -1
- package/dist/components/p-C3gFyogx.js +5 -0
- package/dist/components/p-CI0_r45y.js +5 -0
- package/dist/components/p-CJkthPWR.js +5 -0
- package/dist/components/{p-BxGye2qd.js → p-COKUmuuf.js} +1 -1
- package/dist/components/{p-D4aXUm2Y.js → p-CQ0f2MVb.js} +1 -1
- package/dist/components/{p-ByrX91PC.js → p-CYj0zRtR.js} +1 -1
- package/dist/components/{p-DOIpj5PH.js → p-C_91yYxZ.js} +1 -1
- package/dist/components/p-CbIjjt3n.js +5 -0
- package/dist/components/{p-BhekdMkM.js → p-CpX72zLP.js} +1 -1
- package/dist/components/{p-DkCqJ072.js → p-Cuy8EM9Y.js} +1 -1
- package/dist/components/p-CwYr8ZOV.js +5 -0
- package/dist/components/{p-BySGDlQi.js → p-Cy-0pkLa.js} +1 -1
- package/dist/components/p-DDWKS6lH.js +5 -0
- package/dist/components/p-DJr19tRD.js +5 -0
- package/dist/components/p-DNpppK6M.js +5 -0
- package/dist/components/{p-D_uU2Pi-.js → p-DRtn1_4P.js} +1 -1
- package/dist/components/{p-BwoBk7eI.js → p-D_2r73sx.js} +1 -1
- package/dist/components/p-De3WmHLm.js +5 -0
- package/dist/components/{p-BvM3siIc.js → p-DokN3NzH.js} +1 -1
- package/dist/components/{p-D4VK-Fv7.js → p-DqCIuURq.js} +1 -1
- package/dist/components/{p-DConDqrK.js → p-DuaTomIT.js} +1 -1
- package/dist/components/{p-DVkAlTjC.js → p-DzPqV0I6.js} +1 -1
- package/dist/components/p-GgvQ0B7I.js +5 -0
- package/dist/components/p-HVSqY6-d.js +5 -0
- package/dist/components/{p-DCO6piZ9.js → p-RKSY-Miv.js} +1 -1
- package/dist/components/p-Ty1rh9Up.js +5 -0
- package/dist/components/{p-AkWKeTFc.js → p-VTefgaxv.js} +1 -1
- package/dist/components/{p-DDTSLfBG.js → p-_8V0swcd.js} +1 -1
- package/dist/components/{p-B2Rwfoy0.js → p-ge2RA7lk.js} +1 -1
- package/dist/components/p-mZnLUhNr.js +5 -0
- package/dist/components/{p-CbRoCi89.js → p-mzWr8UUl.js} +1 -1
- package/dist/components/{p-D8w2fZLP.js → p-wX0fQQYY.js} +1 -1
- package/dist/components/{p-CETvww16.js → p-x1Tlf19a.js} +1 -1
- package/dist/components/p-z7jdJ402.js +5 -0
- package/dist/components/part-lookup.js +1 -1
- package/dist/components/service-booking-form.js +1 -1
- package/dist/components/shift-accordion.js +1 -1
- package/dist/components/shift-checkbox.js +1 -1
- package/dist/components/shift-portal.js +1 -1
- package/dist/components/shift-select-dropdown.js +1 -1
- package/dist/components/shift-select.js +1 -1
- package/dist/components/shift-slider.js +1 -1
- package/dist/components/shift-switch.js +1 -1
- package/dist/components/shift-tab-content.js +1 -1
- package/dist/components/shift-tabs.js +1 -1
- package/dist/components/ssc-lookup-form.js +1 -1
- package/dist/components/test-drive-form.js +1 -1
- package/dist/components/vehicle-accessories.js +1 -1
- package/dist/components/vehicle-claimable-items.js +1 -1
- package/dist/components/vehicle-item-claim-form.js +1 -1
- package/dist/components/vehicle-lookup.js +1 -1
- package/dist/components/vehicle-paint-thickness.js +1 -1
- package/dist/components/vehicle-quotation-form.js +1 -1
- package/dist/components/vehicle-sale-information.js +1 -1
- package/dist/components/vehicle-service-history.js +1 -1
- package/dist/components/vehicle-specification.js +1 -1
- package/dist/components/vehicle-ssc.js +1 -1
- package/dist/components/vehicle-warranty-timeline.js +1 -1
- package/dist/esm/{add-icon-DHh6DJXR.js → add-icon-D9Jel7-B.js} +1 -1
- package/dist/esm/{app-globals-CusTGK9D.js → app-globals-inc67m-q.js} +1 -1
- package/dist/esm/{arrow-up-icon-Dw_d-rG9.js → arrow-up-icon-Dfl2olS1.js} +1 -1
- package/dist/esm/branch-date-dropdown_17.entry.js +51 -45
- package/dist/esm/{calendar-days-icon-CnASOv7M.js → calendar-days-icon-zUqcb-fP.js} +1 -1
- package/dist/esm/{check-icon-BZQF4tzH.js → check-icon-CcYgNcDZ.js} +1 -1
- package/dist/esm/clock-DDWKS6lH.js +27 -0
- package/dist/esm/dead-stock-lookup_3.entry.js +10 -9
- package/dist/esm/{decode-time-offset-Cib1aJfV.js → decode-time-offset-CDd68_1V.js} +10 -2
- package/dist/esm/flexible-container.entry.js +2 -2
- package/dist/esm/form-checkbox.entry.js +3 -3
- package/dist/esm/form-date-picker.entry.js +25 -19
- package/dist/esm/{form-error-message-DWl6p6Dz.js → form-error-message-DxLEOczK.js} +1 -1
- package/dist/esm/{form-input-label-6blOw1BN.js → form-input-label-DEqq8CcC.js} +1 -1
- package/dist/esm/form-input_7.entry.js +13 -13
- package/dist/esm/form-switch.entry.js +3 -3
- package/dist/esm/form-time-picker.entry.js +4 -4
- package/dist/esm/{functions-SHZO3nZB.js → functions-M6Gsc8Mz.js} +5 -4
- package/dist/esm/general-form.entry.js +11 -10
- package/dist/esm/general-inquiry-form.entry.js +11 -10
- package/dist/esm/{get-language-from-url-fV-K15uy.js → get-language-from-url-Bq07dpsD.js} +1 -1
- package/dist/esm/{get-local-language-BLpgwBTx.js → get-local-language-D9DW53vG.js} +2 -2
- package/dist/esm/get-mock-files-DQV5ioOw.js +59 -0
- package/dist/esm/{index-CteZTPhq.js → index-CsEiWLCt.js} +3 -1
- package/dist/esm/information-table.entry.js +3 -3
- package/dist/esm/{loader-icon-BvAmA41s.js → loader-icon-CbaFiiB_.js} +1 -1
- package/dist/esm/loader.js +4 -4
- package/dist/esm/loading-spinner.entry.js +1 -1
- package/dist/esm/manufacturer-part-lookup.entry.js +4 -4
- package/dist/esm/{mappers-CZs2R7k6.js → mappers-DOWx0ySR.js} +10 -8
- package/dist/esm/{material-card-jbQd-0as.js → material-card-CB2xHWMN.js} +1 -1
- package/dist/esm/mock-assets-Bixlrdd4.js +11 -0
- package/dist/esm/part-lookup.entry.js +4 -4
- package/dist/esm/{qr-code-scan-B1nViqZl.js → qr-code-scan-FY8RR9ow.js} +1 -1
- package/dist/esm/{reveal-below-DWXRi5w3.js → reveal-below-8wAOxdZk.js} +1 -1
- package/dist/esm/service-booking-form.entry.js +11 -10
- package/dist/esm/shift-accordion.entry.js +1 -1
- package/dist/esm/shift-checkbox.entry.js +3 -3
- package/dist/esm/shift-components.js +4 -4
- package/dist/esm/shift-slider.entry.js +1 -1
- package/dist/esm/shift-switch.entry.js +2 -2
- package/dist/esm/shift-tab-content.entry.js +2 -2
- package/dist/esm/shift-tabs_2.entry.js +7 -7
- package/dist/esm/ssc-lookup-form.entry.js +11 -10
- package/dist/esm/test-drive-form.entry.js +11 -10
- package/dist/esm/{triangle-alert-BlnfPzWh.js → triangle-alert-DNqiuE_3.js} +1 -1
- package/dist/esm/vehicle-accessories_8.entry.js +73 -45
- package/dist/esm/{vehicle-info-layout-Dmx94GLp.js → vehicle-info-layout-I6iG9Fcg.js} +1 -1
- package/dist/esm/vehicle-lookup.entry.js +21 -17
- package/dist/esm/vehicle-quotation-form.entry.js +8 -7
- package/dist/esm/{white-loader-B3tJFuNO.js → white-loader-DusGamWD.js} +1 -1
- package/dist/integration-manifest.json +19 -9
- package/dist/mocks/assets/README.md +54 -0
- package/dist/mocks/assets/accessories/accessory.svg +10 -0
- package/dist/mocks/assets/accessories/floor-mats.svg +10 -0
- package/dist/mocks/assets/accessories/mud-guards.svg +11 -0
- package/dist/mocks/assets/accessories/roof-rack.svg +11 -0
- package/dist/mocks/assets/accessories/roof-rails.svg +11 -0
- package/dist/mocks/assets/accessories/side-steps.svg +11 -0
- package/dist/mocks/assets/accessories/tow-bar.svg +12 -0
- package/dist/mocks/assets/badges/badge-1.svg +5 -0
- package/dist/mocks/assets/badges/badge-2.svg +5 -0
- package/dist/mocks/assets/badges/badge-3.svg +5 -0
- package/dist/mocks/assets/badges/badge-4.svg +5 -0
- package/dist/mocks/assets/badges/badge-5.svg +5 -0
- package/dist/mocks/assets/badges/badge-6.svg +5 -0
- package/dist/mocks/assets/documents/service-invoice-qr.svg +18 -0
- package/dist/mocks/assets/documents/signed-claim-document.svg +21 -0
- package/dist/mocks/assets/paint-panels/door-front-left-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/door-front-left.svg +6 -0
- package/dist/mocks/assets/paint-panels/door-front-right-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/door-front-right.svg +6 -0
- package/dist/mocks/assets/paint-panels/door-rear-left-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/door-rear-left.svg +6 -0
- package/dist/mocks/assets/paint-panels/door-rear-right-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/door-rear-right.svg +6 -0
- package/dist/mocks/assets/paint-panels/fender-front-left-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/fender-front-left.svg +6 -0
- package/dist/mocks/assets/paint-panels/fender-front-right-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/fender-front-right.svg +6 -0
- package/dist/mocks/assets/paint-panels/fender-rear-left-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/fender-rear-left.svg +6 -0
- package/dist/mocks/assets/paint-panels/fender-rear-right-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/fender-rear-right.svg +6 -0
- package/dist/mocks/assets/paint-panels/hood-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/hood.svg +6 -0
- package/dist/mocks/assets/paint-panels/panel.svg +6 -0
- package/dist/mocks/assets/paint-panels/roof-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/roof.svg +6 -0
- package/dist/mocks/assets/paint-panels/tail-gate-detail.svg +7 -0
- package/dist/mocks/assets/paint-panels/tail-gate.svg +6 -0
- package/dist/shift-components/{p-c40bda31.entry.js → p-0395b900.entry.js} +1 -1
- package/dist/shift-components/{p-be19d7ff.entry.js → p-041ff6e5.entry.js} +1 -1
- package/dist/shift-components/p-131c79c9.entry.js +5 -0
- package/dist/shift-components/{p-3895d8e5.entry.js → p-287c5e75.entry.js} +1 -1
- package/dist/shift-components/{p-164eeced.entry.js → p-30be4db4.entry.js} +1 -1
- package/dist/shift-components/p-3c735b0a.entry.js +5 -0
- package/dist/shift-components/{p-90034cd8.entry.js → p-4c826390.entry.js} +1 -1
- package/dist/shift-components/p-6833930c.entry.js +5 -0
- package/dist/shift-components/{p-391c55af.entry.js → p-7760cb43.entry.js} +1 -1
- package/dist/shift-components/p-81a7b7dd.entry.js +5 -0
- package/dist/shift-components/p-82adf890.entry.js +5 -0
- package/dist/shift-components/{p-3790e469.entry.js → p-91d15921.entry.js} +1 -1
- package/dist/shift-components/{p-005d0a3a.entry.js → p-9f017e84.entry.js} +1 -1
- package/dist/shift-components/p-B2ivJ0St.js +5 -0
- package/dist/shift-components/{p-Tjvj6pk4.js → p-BHLT4-AT.js} +1 -1
- package/dist/shift-components/p-BKobZCvH.js +5 -0
- package/dist/shift-components/{p-MzYTUgsB.js → p-BTJYrubY.js} +1 -1
- package/dist/shift-components/p-BTfrQeMt.js +5 -0
- package/dist/shift-components/{p-BkVfhjgg.js → p-Bxxrkd94.js} +1 -1
- package/dist/shift-components/{p-C8PvXL-3.js → p-C7KIr58m.js} +1 -1
- package/dist/shift-components/{p-Ccwtsrgg.js → p-CHQ9vjK9.js} +1 -1
- package/dist/shift-components/{p-DzV_ls5o.js → p-CTvdWiVG.js} +1 -1
- package/dist/shift-components/p-CTy3HfBE.js +5 -0
- package/dist/shift-components/{p-oQAUbfw7.js → p-Cet0ur1z.js} +1 -1
- package/dist/shift-components/{p-OlAbjfKx.js → p-Cn5_F5mW.js} +1 -1
- package/dist/shift-components/p-CsEiWLCt.js +6 -0
- package/dist/shift-components/{p-oFzLYYzz.js → p-D5QsRU5_.js} +1 -1
- package/dist/shift-components/p-DBog8aSI.js +5 -0
- package/dist/shift-components/p-DDWKS6lH.js +5 -0
- package/dist/shift-components/{p-DtD7FZCG.js → p-DZGcyLWV.js} +1 -1
- package/dist/shift-components/p-Dh2tKZeJ.js +5 -0
- package/dist/shift-components/{p-BTNA9XsD.js → p-DxRW_Tfa.js} +1 -1
- package/dist/shift-components/{p-D7cqTTll.js → p-M1S8gM54.js} +1 -1
- package/dist/shift-components/p-a863f984.entry.js +5 -0
- package/dist/shift-components/p-a8c58abe.entry.js +5 -0
- package/dist/shift-components/p-b6dfb75b.entry.js +5 -0
- package/dist/shift-components/{p-d47428d1.entry.js → p-bcfc5126.entry.js} +1 -1
- package/dist/shift-components/{p-879faeec.entry.js → p-c20b97c6.entry.js} +1 -1
- package/dist/shift-components/p-c7e694c0.entry.js +5 -0
- package/dist/shift-components/p-ceeebc95.entry.js +5 -0
- package/dist/shift-components/p-d118078b.entry.js +5 -0
- package/dist/shift-components/{p-af71f000.entry.js → p-d89b19fa.entry.js} +1 -1
- package/dist/shift-components/p-dc408027.entry.js +5 -0
- package/dist/shift-components/p-e3c2fb00.entry.js +5 -0
- package/dist/shift-components/{p-f638970e.entry.js → p-e3f9e20f.entry.js} +1 -1
- package/dist/shift-components/p-f6ca88a5.entry.js +5 -0
- package/dist/shift-components/{p-bfwabdVa.js → p-h1L6xTqG.js} +1 -1
- package/dist/shift-components/p-iSEtUbmS.js +5 -0
- package/dist/shift-components/p-xtI4pqVk.js +5 -0
- package/dist/shift-components/shift-components.esm.js +1 -1
- package/dist/stencil-docs.json +501 -1
- package/dist/types/components/form-elements/branch-date-picker.d.ts +2 -0
- package/dist/types/components/form-elements/branch-slot-picker.d.ts +2 -0
- package/dist/types/components/form-elements/form-date-picker-legacy.d.ts +4 -0
- package/dist/types/components/form-elements/form-picker-input.d.ts +2 -0
- package/dist/types/components/form-elements/form-structure.d.ts +1 -0
- package/dist/types/components/forms/general-form.d.ts +2 -0
- package/dist/types/components/forms/general-inquiry.d.ts +2 -0
- package/dist/types/components/forms/service-booking.d.ts +2 -0
- package/dist/types/components/forms/ssc-lookup.d.ts +2 -0
- package/dist/types/components/forms/test-drive.d.ts +2 -0
- package/dist/types/components/forms/vehicle-quotation.d.ts +2 -0
- package/dist/types/components/vehicle-lookup/vehicle-accessories.d.ts +1 -0
- package/dist/types/components/vehicle-lookup/vehicle-claimable-items.d.ts +1 -0
- package/dist/types/components/vehicle-lookup/vehicle-lookup.d.ts +5 -1
- package/dist/types/components/vehicle-lookup/vehicle-paint-thickness.d.ts +1 -0
- package/dist/types/components/vehicle-lookup/vehicle-sale-information.d.ts +1 -0
- package/dist/types/components/vehicle-lookup/vehicle-service-history.d.ts +1 -0
- package/dist/types/components/vehicle-lookup/vehicle-specification.d.ts +1 -0
- package/dist/types/components/vehicle-lookup/vehicle-ssc.d.ts +14 -1
- package/dist/types/components/vehicle-lookup/vehicle-warranty-timeline.d.ts +2 -0
- package/dist/types/components.d.ts +136 -0
- package/dist/types/features/form-hook/interface.d.ts +1 -0
- package/dist/types/features/mocks/index.d.ts +1 -0
- package/dist/types/features/mocks/mock-assets.d.ts +1 -0
- package/dist/types/features/vehicle-lookup-component/interface.d.ts +1 -0
- package/dist/types/global/lib/clock.d.ts +11 -0
- package/dist/types/global/lib/decode-time-offset.d.ts +2 -1
- package/package.json +2 -1
- package/dist/cjs/get-mock-files-NMHm1Vgn.js +0 -53
- package/dist/collection/global/api/urls.js +0 -6
- package/dist/collection/templates/vehicle-lookup/mock-data.js +0 -4922
- package/dist/collection/templates/vehicle-lookup/mock-loader.js +0 -26
- package/dist/collection/templates/vehicle-lookup/warranty-mock-data.js +0 -3211
- package/dist/components/p-B4nj03om.js +0 -5
- package/dist/components/p-BDCBfHZQ.js +0 -5
- package/dist/components/p-BGf2deKN.js +0 -5
- package/dist/components/p-BNmsN10T.js +0 -5
- package/dist/components/p-BOaqSzZZ.js +0 -5
- package/dist/components/p-BpZlI-gl.js +0 -5
- package/dist/components/p-C9uBduBY.js +0 -5
- package/dist/components/p-CUO3vXQr.js +0 -5
- package/dist/components/p-DJDhhX5A.js +0 -5
- package/dist/components/p-DKWqzBVM.js +0 -5
- package/dist/components/p-DfVskL_i.js +0 -5
- package/dist/components/p-DpuHkgw0.js +0 -5
- package/dist/components/p-Imck426q.js +0 -5
- package/dist/components/p-XFwQkeZH.js +0 -5
- package/dist/components/p-a4ooD0o_.js +0 -5
- package/dist/components/p-d7wdNFwt.js +0 -5
- package/dist/components/p-vlA3PJQv.js +0 -5
- package/dist/esm/get-mock-files-Dpb0udoz.js +0 -51
- package/dist/mocks/generated/broker-dealer/paint-thickness-certificate.json +0 -1
- package/dist/mocks/generated/broker-dealer/part-lookup.json +0 -155
- package/dist/mocks/generated/broker-dealer/vehicle-lookup.json +0 -794
- package/dist/mocks/generated/edge-cases/paint-thickness-certificate.json +0 -1
- package/dist/mocks/generated/edge-cases/part-lookup.json +0 -1
- package/dist/mocks/generated/edge-cases/vehicle-lookup.json +0 -124
- package/dist/mocks/generated/standard-dealer/paint-thickness-certificate.json +0 -146
- package/dist/mocks/generated/standard-dealer/part-lookup.json +0 -157
- package/dist/mocks/generated/standard-dealer/vehicle-lookup.json +0 -809
- package/dist/shift-components/p-0965eb41.entry.js +0 -5
- package/dist/shift-components/p-219e589c.entry.js +0 -5
- package/dist/shift-components/p-3324bdf6.entry.js +0 -5
- package/dist/shift-components/p-3ba3f543.entry.js +0 -5
- package/dist/shift-components/p-48Fp2I0C.js +0 -5
- package/dist/shift-components/p-5c28fb6d.entry.js +0 -5
- package/dist/shift-components/p-60232b66.entry.js +0 -5
- package/dist/shift-components/p-82bb8960.entry.js +0 -5
- package/dist/shift-components/p-93ddc847.entry.js +0 -5
- package/dist/shift-components/p-B9INqdFT.js +0 -5
- package/dist/shift-components/p-C4NpWwNE.js +0 -5
- package/dist/shift-components/p-C_QDvFTV.js +0 -5
- package/dist/shift-components/p-CteZTPhq.js +0 -6
- package/dist/shift-components/p-DIe_G0iC.js +0 -5
- package/dist/shift-components/p-DWoutohJ.js +0 -5
- package/dist/shift-components/p-a4f1502c.entry.js +0 -5
- package/dist/shift-components/p-bd8dbd1d.entry.js +0 -5
- package/dist/shift-components/p-d8844424.entry.js +0 -5
- package/dist/shift-components/p-e7986265.entry.js +0 -5
- package/dist/shift-components/p-f93d79bc.entry.js +0 -5
- package/dist/shift-components/p-fa296247.entry.js +0 -5
- package/dist/shift-components/p-pkYWYULB.js +0 -5
- package/dist/types/global/api/urls.d.ts +0 -2
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides the `harness()` Alpine data factory and stamps the shared chrome into
|
|
5
5
|
* the placeholder elements below, so a page describes what it is testing instead
|
|
6
|
-
* of re-implementing navigation and the
|
|
6
|
+
* of re-implementing navigation and the shared controls:
|
|
7
7
|
*
|
|
8
8
|
* <div data-harness-nav x-cloak></div>
|
|
9
9
|
*
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
*
|
|
22
22
|
* …and the controls, split by how often you touch them:
|
|
23
23
|
*
|
|
24
|
-
* [data-harness-bar]
|
|
25
|
-
*
|
|
26
|
-
* [data-harness-rail]
|
|
27
|
-
*
|
|
28
|
-
*
|
|
24
|
+
* [data-harness-bar] Fixtures, inline above the component. Reached in one
|
|
25
|
+
* click, because that is every interaction.
|
|
26
|
+
* [data-harness-rail] Connection, Environment, Today, language, theme,
|
|
27
|
+
* platform width and the event log, in a drawer behind a
|
|
28
|
+
* tab on the right edge (a button on a phone).
|
|
29
29
|
*
|
|
30
30
|
* The rail used to be a 300px aside, which cost the component under test a third
|
|
31
31
|
* of the page on every demo. Its stamped markup is all `position: fixed`, so the
|
|
@@ -46,6 +46,23 @@
|
|
|
46
46
|
* .shift/repos/adp/web-components/templates-design-language.md.
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
+
import { chooseEnvironment, environmentFileUrl, environmentLabel, environmentsFrom } from './harness-environment.js';
|
|
50
|
+
import {
|
|
51
|
+
captureConnectionState,
|
|
52
|
+
clearConnection,
|
|
53
|
+
connectProfile,
|
|
54
|
+
connectionFields,
|
|
55
|
+
connectionLog,
|
|
56
|
+
connectionOptions,
|
|
57
|
+
connectionStorageKey,
|
|
58
|
+
disconnectProfile,
|
|
59
|
+
emptyConnectionDraft,
|
|
60
|
+
loadConnection,
|
|
61
|
+
saveConnection,
|
|
62
|
+
todayChoiceAvailable,
|
|
63
|
+
validateConnection,
|
|
64
|
+
} from './harness-connection.js';
|
|
65
|
+
|
|
49
66
|
/*
|
|
50
67
|
* Every path this file emits or compares is resolved against the directory this
|
|
51
68
|
* module was loaded from, never against the server root. Root-absolute paths
|
|
@@ -58,6 +75,41 @@
|
|
|
58
75
|
* tags; the fix has to be here, where `import.meta.url` knows the real depth.
|
|
59
76
|
*/
|
|
60
77
|
const SITE_ROOT = new URL('../', import.meta.url);
|
|
78
|
+
const ENVIRONMENT_STORAGE_KEY = 'adp-harness-environment';
|
|
79
|
+
const ENVIRONMENT_SETTLE_MS = 320;
|
|
80
|
+
const TODAY_STORAGE_KEY = 'adp-harness-today';
|
|
81
|
+
const TODAY_MODE_STORAGE_KEY = 'adp-harness-today-mode';
|
|
82
|
+
const ISO_CALENDAR_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
83
|
+
|
|
84
|
+
const wallToday = () => new Date().toISOString().slice(0, 10);
|
|
85
|
+
|
|
86
|
+
const isCalendarDate = value => {
|
|
87
|
+
if (!ISO_CALENDAR_DATE.test(value || '')) return false;
|
|
88
|
+
|
|
89
|
+
const resolved = new Date(`${value}T00:00:00.000Z`);
|
|
90
|
+
return !Number.isNaN(resolved.getTime()) && resolved.toISOString().slice(0, 10) === value;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const readStoredToday = () => {
|
|
94
|
+
try {
|
|
95
|
+
return {
|
|
96
|
+
mode: localStorage.getItem(TODAY_MODE_STORAGE_KEY),
|
|
97
|
+
value: localStorage.getItem(TODAY_STORAGE_KEY),
|
|
98
|
+
};
|
|
99
|
+
} catch {
|
|
100
|
+
return { mode: null, value: null };
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const readStoredEnvironment = () => {
|
|
105
|
+
try {
|
|
106
|
+
return sessionStorage.getItem(ENVIRONMENT_STORAGE_KEY);
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const afterEnvironmentSettles = () => new Promise(resolve => setTimeout(resolve, ENVIRONMENT_SETTLE_MS));
|
|
61
113
|
|
|
62
114
|
/** A catalog path (`/templates/…`) as a URL path valid from wherever this page sits. */
|
|
63
115
|
const site = value => new URL(String(value).replace(/^\//, ''), SITE_ROOT).pathname;
|
|
@@ -81,7 +133,7 @@ function fail(message) {
|
|
|
81
133
|
}
|
|
82
134
|
|
|
83
135
|
/**
|
|
84
|
-
* The
|
|
136
|
+
* The five component shapes these demos drive. A profile is only a bundle of
|
|
85
137
|
* defaults — every field it sets can still be overridden per page.
|
|
86
138
|
*
|
|
87
139
|
* `events` maps a component callback property to a log line. Handlers run with
|
|
@@ -90,10 +142,10 @@ function fail(message) {
|
|
|
90
142
|
*/
|
|
91
143
|
const PROFILES = {
|
|
92
144
|
// vehicle-lookup family: a VIN goes in, one response comes back.
|
|
93
|
-
lookup: {
|
|
145
|
+
'lookup': {
|
|
94
146
|
apply: (subject, data) => subject.setMockData(data),
|
|
95
147
|
select: (subject, key) => subject.fetchVin(key),
|
|
96
|
-
|
|
148
|
+
clear: subject => (subject.clearData ? subject.clearData() : subject.fetchVin({ vin: '' })),
|
|
97
149
|
events: {
|
|
98
150
|
loadingStateChange: track,
|
|
99
151
|
errorCallback: fail,
|
|
@@ -101,12 +153,17 @@ const PROFILES = {
|
|
|
101
153
|
},
|
|
102
154
|
},
|
|
103
155
|
|
|
104
|
-
// part-lookup family:
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
156
|
+
// part-lookup family: the harness owns the generated file, while the single
|
|
157
|
+
// panels still receive it through their public mock API. The wrapper has no
|
|
158
|
+
// setMockData method, so a selected DTO is distributed to all three tabs.
|
|
159
|
+
'part': {
|
|
160
|
+
apply: (subject, data) => subject.setMockData?.(data),
|
|
161
|
+
select: (subject, key, harness) => {
|
|
162
|
+
const mock = !harness.connected && harness.data?.[key];
|
|
163
|
+
|
|
164
|
+
return mock && subject.localName === 'part-lookup' ? subject.handleLoadData(mock, null) : subject.fetchData(key);
|
|
165
|
+
},
|
|
166
|
+
clear: subject => (subject.localName === 'part-lookup' ? subject.handleLoadData({ partNumber: '' }, null) : subject.fetchData('')),
|
|
110
167
|
events: {
|
|
111
168
|
loadingStateChange: track,
|
|
112
169
|
errorCallback: fail,
|
|
@@ -123,10 +180,9 @@ const PROFILES = {
|
|
|
123
180
|
|
|
124
181
|
// forms: no fixture list — the structure JSON is the input, and what matters
|
|
125
182
|
// is the submit lifecycle.
|
|
126
|
-
form: {
|
|
183
|
+
'form': {
|
|
127
184
|
apply: null,
|
|
128
185
|
select: null,
|
|
129
|
-
endpoint: subject => subject.structureUrl || subject.getAttribute('structure-url'),
|
|
130
186
|
events: {
|
|
131
187
|
formReadyCallback() {
|
|
132
188
|
this.ready = true;
|
|
@@ -149,19 +205,19 @@ const PROFILES = {
|
|
|
149
205
|
|
|
150
206
|
// vehicle-lookup: the shell that holds the eight single-vehicle components and
|
|
151
207
|
// shows one at a time. It reports its own state rather than the children's.
|
|
152
|
-
composite: {
|
|
153
|
-
apply:
|
|
154
|
-
|
|
208
|
+
'composite': {
|
|
209
|
+
apply: (subject, data) => subject.setMockData(data),
|
|
210
|
+
clear: subject => subject.handleLoadData({ vin: '' }, null),
|
|
155
211
|
// In development, push the fixture into every tab at once instead of only the
|
|
156
212
|
// active one, which is what `fetchVin` does — otherwise switching tabs shows
|
|
157
213
|
// whatever the previous search left behind. Empty and Error have no fixture,
|
|
158
214
|
// so they go the normal route and let each child render its own state.
|
|
159
215
|
select: (subject, key, harness) => {
|
|
160
|
-
const mock = harness.
|
|
216
|
+
const mock = !harness.connected && harness.data?.[key];
|
|
161
217
|
|
|
162
218
|
// A page that sets ssc-query-string is showing the SSC tab's own lookup and what the other
|
|
163
219
|
// tabs' searches leave it with, so its searches go through fetchVin the way a host's do.
|
|
164
|
-
return mock && !subject.sscQueryString ? subject.handleLoadData(mock, null) : subject.fetchVin(key
|
|
220
|
+
return mock && !subject.sscQueryString ? subject.handleLoadData(mock, null) : subject.fetchVin(key);
|
|
165
221
|
},
|
|
166
222
|
events: {
|
|
167
223
|
loadingStateChanged: track,
|
|
@@ -169,6 +225,13 @@ const PROFILES = {
|
|
|
169
225
|
dynamicClaimActivate: information => ['claim activate', information?.vin ?? '(no vin)'],
|
|
170
226
|
},
|
|
171
227
|
},
|
|
228
|
+
|
|
229
|
+
// Gallery page: one Connection value is applied to every OCR-enabled case.
|
|
230
|
+
'vin-extractor': {
|
|
231
|
+
apply: null,
|
|
232
|
+
select: null,
|
|
233
|
+
events: {},
|
|
234
|
+
},
|
|
172
235
|
};
|
|
173
236
|
|
|
174
237
|
const DEFAULTS = {
|
|
@@ -176,9 +239,6 @@ const DEFAULTS = {
|
|
|
176
239
|
profile: 'lookup',
|
|
177
240
|
mocks: null,
|
|
178
241
|
labels: {},
|
|
179
|
-
// Fixture keys to offer in production mode, where there is no mock file to
|
|
180
|
-
// generate them from. Development mode always uses the generated list (R7).
|
|
181
|
-
samples: [],
|
|
182
242
|
// Fixture to run as soon as the subject is ready, so a page can deep-link a
|
|
183
243
|
// scenario (`?vin=…`) instead of asking whoever opened the link to click.
|
|
184
244
|
start: null,
|
|
@@ -196,8 +256,10 @@ const DEFAULTS = {
|
|
|
196
256
|
{ label: 'Full', value: '100%' },
|
|
197
257
|
],
|
|
198
258
|
language: true,
|
|
259
|
+
environment: true,
|
|
260
|
+
today: true,
|
|
199
261
|
theme: true,
|
|
200
|
-
|
|
262
|
+
connection: {},
|
|
201
263
|
platform: true,
|
|
202
264
|
log: true,
|
|
203
265
|
fixtures: null,
|
|
@@ -208,7 +270,7 @@ const DEFAULTS = {
|
|
|
208
270
|
// `undefined` means "take the profile's"; `null` means "this page has none".
|
|
209
271
|
apply: undefined,
|
|
210
272
|
select: undefined,
|
|
211
|
-
|
|
273
|
+
clear: undefined,
|
|
212
274
|
};
|
|
213
275
|
|
|
214
276
|
window.harness = function harness(options = {}) {
|
|
@@ -217,7 +279,11 @@ window.harness = function harness(options = {}) {
|
|
|
217
279
|
|
|
218
280
|
const apply = config.apply === undefined ? profile.apply : config.apply;
|
|
219
281
|
const select = config.select === undefined ? profile.select : config.select;
|
|
220
|
-
const
|
|
282
|
+
const clear = config.clear === undefined ? profile.clear : config.clear;
|
|
283
|
+
const profileName = PROFILES[config.profile] ? config.profile : 'lookup';
|
|
284
|
+
const configuredConnection = connectionOptions(profileName, config.connection);
|
|
285
|
+
const fields = connectionFields(profileName, configuredConnection);
|
|
286
|
+
const storageKey = connectionStorageKey(profileName, window.location.pathname);
|
|
221
287
|
// `false` wires nothing: a page demonstrating the Blazor bridge needs those
|
|
222
288
|
// same callback props left as the attribute strings the component dispatches
|
|
223
289
|
// through the .NET ref, and it feeds the log with `harness:log` instead.
|
|
@@ -231,22 +297,38 @@ window.harness = function harness(options = {}) {
|
|
|
231
297
|
platforms: config.platforms,
|
|
232
298
|
show: {
|
|
233
299
|
language: config.language,
|
|
300
|
+
environment: config.environment && Boolean(config.mocks),
|
|
301
|
+
today: config.today && config.subject !== false,
|
|
234
302
|
theme: config.theme,
|
|
235
|
-
|
|
303
|
+
connection: config.connection !== false && config.subject !== false,
|
|
236
304
|
platform: config.platform,
|
|
237
305
|
log: config.log,
|
|
238
|
-
fixtures: (config.fixtures ?? Boolean(config.mocks
|
|
306
|
+
fixtures: (config.fixtures ?? Boolean(config.mocks)) && Boolean(select),
|
|
239
307
|
// The bar only earns its space when it has something in it.
|
|
240
308
|
get bar() {
|
|
241
|
-
return this.
|
|
309
|
+
return this.fixtures;
|
|
242
310
|
},
|
|
243
311
|
},
|
|
244
312
|
|
|
245
313
|
language: config.languages[0],
|
|
314
|
+
environments: [],
|
|
315
|
+
environment: '',
|
|
316
|
+
environmentChanging: false,
|
|
317
|
+
environmentError: '',
|
|
318
|
+
environmentRequest: 0,
|
|
319
|
+
today: '',
|
|
320
|
+
todayMode: 'live',
|
|
321
|
+
todayAnchor: '',
|
|
322
|
+
customToday: wallToday(),
|
|
323
|
+
generatedTodayChoice: null,
|
|
246
324
|
theme: window.harnessTheme?.current() ?? 'system',
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
325
|
+
connected: false,
|
|
326
|
+
connectionBusy: false,
|
|
327
|
+
connectionError: '',
|
|
328
|
+
connectionErrors: {},
|
|
329
|
+
connectionFields: fields,
|
|
330
|
+
connectionDraft: emptyConnectionDraft(profileName, configuredConnection),
|
|
331
|
+
connectionBaseline: null,
|
|
250
332
|
// The rail is a drawer, not a column: it would otherwise take a third of the
|
|
251
333
|
// width away from the thing under test on every page.
|
|
252
334
|
open: false,
|
|
@@ -261,6 +343,7 @@ window.harness = function harness(options = {}) {
|
|
|
261
343
|
// How many fixtures `has` filtered out. Shown, never silently dropped.
|
|
262
344
|
hidden: 0,
|
|
263
345
|
fixture: null,
|
|
346
|
+
generatedFixture: null,
|
|
264
347
|
// Forms flip this from formReadyCallback; an external submit button waits on it.
|
|
265
348
|
ready: false,
|
|
266
349
|
lines: [],
|
|
@@ -269,17 +352,39 @@ window.harness = function harness(options = {}) {
|
|
|
269
352
|
return config.rtl.includes(this.language) ? 'rtl' : 'ltr';
|
|
270
353
|
},
|
|
271
354
|
|
|
355
|
+
get todayLabel() {
|
|
356
|
+
return this.todayMode === 'live' ? wallToday() : this.today;
|
|
357
|
+
},
|
|
358
|
+
|
|
359
|
+
get environmentLabel() {
|
|
360
|
+
return environmentLabel(this.environment);
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
get connectionLabel() {
|
|
364
|
+
return this.connected ? 'Live' : 'Generated';
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
get liveTodayExplanation() {
|
|
368
|
+
return 'Live API responses use the server’s current time. Disconnect to use the generated Anchor or Custom choices.';
|
|
369
|
+
},
|
|
370
|
+
|
|
272
371
|
/** Empty and Error are always offered; the rest is generated, never listed (R7). */
|
|
273
372
|
get fixtures() {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
return [{ value: '', label: 'Empty' }, { value: 'error', label: 'Error' }, ...keys.map(key => ({ value: key, label: key, note: config.labels[key] }))];
|
|
373
|
+
return [{ value: '', label: 'Empty' }, { value: 'error', label: 'Error' }, ...this.keys.map(key => ({ value: key, label: key, note: config.labels[key] }))];
|
|
277
374
|
},
|
|
278
375
|
|
|
279
376
|
async init() {
|
|
280
377
|
// Any script on the page can write to the log without an Alpine scope.
|
|
281
378
|
window.addEventListener('harness:log', event => this.write(event.detail?.label, event.detail?.detail));
|
|
282
379
|
|
|
380
|
+
// `source` was the temporary bridge to generated fixtures. The picker is
|
|
381
|
+
// now the only source selector, so retire the parameter wherever it appears.
|
|
382
|
+
const initialUrl = new URL(window.location.href);
|
|
383
|
+
if (initialUrl.searchParams.has('source')) {
|
|
384
|
+
initialUrl.searchParams.delete('source');
|
|
385
|
+
window.history.replaceState({}, '', initialUrl);
|
|
386
|
+
}
|
|
387
|
+
|
|
283
388
|
// A gallery page drives several elements itself and has no single subject.
|
|
284
389
|
if (config.subject === false) return;
|
|
285
390
|
|
|
@@ -294,15 +399,22 @@ window.harness = function harness(options = {}) {
|
|
|
294
399
|
|
|
295
400
|
await config.setup?.(this.subject, this);
|
|
296
401
|
|
|
402
|
+
if (typeof configuredConnection.targets === 'string') configuredConnection.targets = [...document.querySelectorAll(configuredConnection.targets)];
|
|
403
|
+
|
|
404
|
+
this.connectionBaseline = captureConnectionState(profileName, this.subject, configuredConnection);
|
|
405
|
+
|
|
297
406
|
if (config.language) this.setLanguage(this.subject.language || this.language);
|
|
407
|
+
if (config.mocks) await this.initEnvironment();
|
|
408
|
+
if (config.today) await this.initToday();
|
|
298
409
|
|
|
299
410
|
// Before isDev, not after: flipping it makes some components load their own
|
|
300
411
|
// mock file and call straight back, so the listeners have to be in place.
|
|
301
412
|
this.observe();
|
|
302
|
-
this.subject.isDev = true;
|
|
413
|
+
if (profileName !== 'vin-extractor') this.subject.isDev = true;
|
|
303
414
|
|
|
304
|
-
|
|
305
|
-
|
|
415
|
+
await this.restoreConnection();
|
|
416
|
+
|
|
417
|
+
if (!this.connected && config.start && this.keys.includes(config.start)) this.run(config.start);
|
|
306
418
|
},
|
|
307
419
|
|
|
308
420
|
/* ---------- controls ---------- */
|
|
@@ -324,6 +436,321 @@ window.harness = function harness(options = {}) {
|
|
|
324
436
|
this.write('language', `${language} · ${this.dir}`);
|
|
325
437
|
},
|
|
326
438
|
|
|
439
|
+
async initEnvironment() {
|
|
440
|
+
try {
|
|
441
|
+
const response = await fetch(new URL('mocks/generated/index.json', SITE_ROOT));
|
|
442
|
+
if (!response.ok) throw new Error(`${response.status}`);
|
|
443
|
+
|
|
444
|
+
this.environments = environmentsFrom(await response.json());
|
|
445
|
+
if (!this.environments.length) throw new Error('the generated index contains no environments');
|
|
446
|
+
|
|
447
|
+
const url = new URL(window.location.href);
|
|
448
|
+
const selected = chooseEnvironment(this.environments, url.searchParams.get('env'), readStoredEnvironment());
|
|
449
|
+
|
|
450
|
+
await this.loadEnvironment(selected.name, true);
|
|
451
|
+
} catch (error) {
|
|
452
|
+
this.environmentError = `Failed to load generated environments — ${error.message}`;
|
|
453
|
+
this.write('environment', this.environmentError);
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
|
|
457
|
+
async setEnvironment(name) {
|
|
458
|
+
if (this.connected || !name || name === this.environment || this.environmentChanging) return;
|
|
459
|
+
|
|
460
|
+
await this.loadEnvironment(name, false);
|
|
461
|
+
},
|
|
462
|
+
|
|
463
|
+
async loadEnvironment(name, initial) {
|
|
464
|
+
const selected = this.environments.find(environment => environment.name === name);
|
|
465
|
+
if (!selected) return;
|
|
466
|
+
|
|
467
|
+
const request = ++this.environmentRequest;
|
|
468
|
+
const mockUrl = environmentFileUrl(SITE_ROOT, selected.name, config.mocks);
|
|
469
|
+
|
|
470
|
+
this.environment = selected.name;
|
|
471
|
+
this.environmentError = '';
|
|
472
|
+
this.fixture = '';
|
|
473
|
+
this.data = null;
|
|
474
|
+
this.keys = [];
|
|
475
|
+
this.hidden = 0;
|
|
476
|
+
this.todayAnchor = isCalendarDate(selected.anchor) ? selected.anchor : '';
|
|
477
|
+
this.subject.mockUrl = mockUrl.href;
|
|
478
|
+
|
|
479
|
+
const url = new URL(window.location.href);
|
|
480
|
+
url.searchParams.delete('source');
|
|
481
|
+
url.searchParams.set('env', selected.name);
|
|
482
|
+
if (!initial) {
|
|
483
|
+
url.searchParams.delete('vin');
|
|
484
|
+
url.searchParams.delete('claim');
|
|
485
|
+
}
|
|
486
|
+
window.history.replaceState({}, '', url);
|
|
487
|
+
|
|
488
|
+
try {
|
|
489
|
+
sessionStorage.setItem(ENVIRONMENT_STORAGE_KEY, selected.name);
|
|
490
|
+
} catch {
|
|
491
|
+
// Storage can be unavailable in privacy modes; the URL remains authoritative.
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Anchor follows the environment; Live and Custom deliberately do not.
|
|
495
|
+
if (!initial && this.todayMode === 'anchor') this.setToday('anchor');
|
|
496
|
+
|
|
497
|
+
if (!initial) {
|
|
498
|
+
this.environmentChanging = true;
|
|
499
|
+
this.setEnvironmentTransition(true);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
try {
|
|
503
|
+
if (!initial) {
|
|
504
|
+
await afterEnvironmentSettles();
|
|
505
|
+
await clear?.(this.subject, this);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const response = await fetch(mockUrl);
|
|
509
|
+
if (!response.ok) throw new Error(`${response.status}`);
|
|
510
|
+
|
|
511
|
+
const data = (await response.json()) ?? {};
|
|
512
|
+
if (request !== this.environmentRequest) return;
|
|
513
|
+
|
|
514
|
+
this.data = data;
|
|
515
|
+
await apply?.(this.subject, data);
|
|
516
|
+
this.setFixtures(Object.keys(data), data);
|
|
517
|
+
this.write('environment', `${selected.name} · ${this.keys.length} shown`);
|
|
518
|
+
} catch (error) {
|
|
519
|
+
if (request !== this.environmentRequest) return;
|
|
520
|
+
|
|
521
|
+
this.data = {};
|
|
522
|
+
this.setFixtures([], {});
|
|
523
|
+
this.environmentError = `Failed to load ${selected.name} — ${error.message}`;
|
|
524
|
+
this.write('environment', this.environmentError);
|
|
525
|
+
} finally {
|
|
526
|
+
if (!initial && request === this.environmentRequest) {
|
|
527
|
+
this.environmentChanging = false;
|
|
528
|
+
this.setEnvironmentTransition(false);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
setEnvironmentTransition(changing) {
|
|
534
|
+
this.subject
|
|
535
|
+
.closest('section')
|
|
536
|
+
?.querySelectorAll('.frame')
|
|
537
|
+
.forEach(frame => frame.setAttribute('data-environment-changing', String(changing)));
|
|
538
|
+
},
|
|
539
|
+
|
|
540
|
+
async initToday() {
|
|
541
|
+
const url = new URL(window.location.href);
|
|
542
|
+
|
|
543
|
+
const requested = url.searchParams.get('today');
|
|
544
|
+
|
|
545
|
+
if (isCalendarDate(requested)) {
|
|
546
|
+
this.customToday = requested;
|
|
547
|
+
this.setToday(requested === this.todayAnchor ? 'anchor' : 'custom', requested);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const stored = readStoredToday();
|
|
552
|
+
|
|
553
|
+
if (stored.mode === 'live') {
|
|
554
|
+
this.setToday('live');
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
if (stored.mode === 'custom' && isCalendarDate(stored.value)) {
|
|
559
|
+
this.customToday = stored.value;
|
|
560
|
+
this.setToday('custom', stored.value);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (this.todayAnchor) {
|
|
565
|
+
this.setToday('anchor');
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
this.setToday('live', this.customToday, false);
|
|
570
|
+
},
|
|
571
|
+
|
|
572
|
+
setToday(mode, customDate = this.customToday, persist = true) {
|
|
573
|
+
if (this.connected && mode !== 'live') return;
|
|
574
|
+
if (mode === 'anchor' && !this.todayAnchor) return;
|
|
575
|
+
if (mode === 'custom' && !isCalendarDate(customDate)) return;
|
|
576
|
+
|
|
577
|
+
const value = mode === 'anchor' ? this.todayAnchor : mode === 'custom' ? customDate : '';
|
|
578
|
+
|
|
579
|
+
this.todayMode = mode;
|
|
580
|
+
this.today = value;
|
|
581
|
+
if (mode === 'custom') this.customToday = customDate;
|
|
582
|
+
this.subject.today = value;
|
|
583
|
+
|
|
584
|
+
const url = new URL(window.location.href);
|
|
585
|
+
if (value) url.searchParams.set('today', value);
|
|
586
|
+
else url.searchParams.delete('today');
|
|
587
|
+
window.history.replaceState({}, '', url);
|
|
588
|
+
|
|
589
|
+
if (persist) {
|
|
590
|
+
try {
|
|
591
|
+
localStorage.setItem(TODAY_MODE_STORAGE_KEY, mode);
|
|
592
|
+
if (value) localStorage.setItem(TODAY_STORAGE_KEY, value);
|
|
593
|
+
else localStorage.removeItem(TODAY_STORAGE_KEY);
|
|
594
|
+
} catch {
|
|
595
|
+
// Storage can be unavailable in privacy modes; the prop and URL still work.
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
this.write('today', mode === 'live' ? `${wallToday()} · live` : `${value} · ${mode}`);
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
canUseToday(mode) {
|
|
603
|
+
return todayChoiceAvailable(mode, this.connected, Boolean(this.todayAnchor));
|
|
604
|
+
},
|
|
605
|
+
|
|
606
|
+
clearConnectionError(name) {
|
|
607
|
+
if (!this.connectionErrors[name] && !this.connectionError) return;
|
|
608
|
+
|
|
609
|
+
this.connectionErrors = { ...this.connectionErrors, [name]: '' };
|
|
610
|
+
this.connectionError = '';
|
|
611
|
+
},
|
|
612
|
+
|
|
613
|
+
async restoreConnection() {
|
|
614
|
+
let settings;
|
|
615
|
+
|
|
616
|
+
try {
|
|
617
|
+
settings = loadConnection(sessionStorage, storageKey, profileName, configuredConnection);
|
|
618
|
+
} catch {
|
|
619
|
+
settings = null;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (!settings) return;
|
|
623
|
+
|
|
624
|
+
this.generatedTodayChoice = { mode: this.todayMode, customDate: this.customToday };
|
|
625
|
+
this.generatedFixture = this.fixture;
|
|
626
|
+
this.connectionBusy = true;
|
|
627
|
+
|
|
628
|
+
try {
|
|
629
|
+
if (profileName === 'form') await this.replaceFormSubject(settings.structureUrl, false);
|
|
630
|
+
|
|
631
|
+
connectProfile(profileName, this.subject, settings, configuredConnection);
|
|
632
|
+
this.connected = true;
|
|
633
|
+
this.fixture = null;
|
|
634
|
+
if (config.today) this.setToday('live', this.customToday, false);
|
|
635
|
+
this.write('connection', connectionLog('connect', profileName));
|
|
636
|
+
} catch {
|
|
637
|
+
try {
|
|
638
|
+
clearConnection(sessionStorage, storageKey);
|
|
639
|
+
} catch {
|
|
640
|
+
// A blocked session store also means there is nothing useful to clear.
|
|
641
|
+
}
|
|
642
|
+
this.connectionError = 'The saved connection could not be applied. Generated data remains active.';
|
|
643
|
+
this.write('connection', 'saved live settings rejected · generated data kept');
|
|
644
|
+
} finally {
|
|
645
|
+
this.connectionBusy = false;
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
|
|
649
|
+
async connect() {
|
|
650
|
+
if (this.connectionBusy || this.connected) return;
|
|
651
|
+
|
|
652
|
+
const validated = validateConnection(profileName, this.connectionDraft, configuredConnection);
|
|
653
|
+
this.connectionErrors = validated.errors;
|
|
654
|
+
|
|
655
|
+
if (!validated.ok) {
|
|
656
|
+
this.connectionError = 'Fix the highlighted connection fields before connecting.';
|
|
657
|
+
this.write('connection', 'validation failed · no values logged');
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
this.connectionError = '';
|
|
662
|
+
this.connectionBusy = true;
|
|
663
|
+
this.generatedTodayChoice = { mode: this.todayMode, customDate: this.customToday };
|
|
664
|
+
this.generatedFixture = this.fixture;
|
|
665
|
+
|
|
666
|
+
try {
|
|
667
|
+
if (profileName === 'form') await this.replaceFormSubject(validated.settings.structureUrl, false);
|
|
668
|
+
else if (profileName !== 'vin-extractor') await clear?.(this.subject, this);
|
|
669
|
+
|
|
670
|
+
connectProfile(profileName, this.subject, validated.settings, configuredConnection);
|
|
671
|
+
|
|
672
|
+
try {
|
|
673
|
+
saveConnection(sessionStorage, storageKey, validated.settings);
|
|
674
|
+
} catch {
|
|
675
|
+
// The connection still works for this page view when storage is blocked.
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
this.connected = true;
|
|
679
|
+
this.fixture = null;
|
|
680
|
+
if (config.today) this.setToday('live', this.customToday, false);
|
|
681
|
+
this.write('connection', connectionLog('connect', profileName));
|
|
682
|
+
} catch {
|
|
683
|
+
disconnectProfile(profileName, this.subject, this.connectionBaseline, configuredConnection);
|
|
684
|
+
this.connectionError = 'The connection could not be applied. Generated data remains active.';
|
|
685
|
+
this.write('connection', 'connect failed · no values logged');
|
|
686
|
+
} finally {
|
|
687
|
+
this.connectionBusy = false;
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
|
|
691
|
+
async disconnect() {
|
|
692
|
+
if (this.connectionBusy || !this.connected) return;
|
|
693
|
+
|
|
694
|
+
this.connectionBusy = true;
|
|
695
|
+
|
|
696
|
+
try {
|
|
697
|
+
try {
|
|
698
|
+
clearConnection(sessionStorage, storageKey);
|
|
699
|
+
} catch {
|
|
700
|
+
// The in-memory state is still cleared below.
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
if (profileName === 'form') await this.replaceFormSubject(this.connectionBaseline.structureUrl, true);
|
|
704
|
+
|
|
705
|
+
disconnectProfile(profileName, this.subject, this.connectionBaseline, configuredConnection);
|
|
706
|
+
this.connected = false;
|
|
707
|
+
this.connectionDraft = emptyConnectionDraft(profileName, configuredConnection);
|
|
708
|
+
this.connectionErrors = {};
|
|
709
|
+
this.connectionError = '';
|
|
710
|
+
|
|
711
|
+
if (config.mocks) {
|
|
712
|
+
await apply?.(this.subject, this.data ?? {});
|
|
713
|
+
|
|
714
|
+
const previous = this.generatedFixture;
|
|
715
|
+
this.fixture = null;
|
|
716
|
+
if (previous === '' || previous === 'error' || this.keys.includes(previous)) await this.run(previous);
|
|
717
|
+
else await clear?.(this.subject, this);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (config.today) {
|
|
721
|
+
const choice = this.generatedTodayChoice;
|
|
722
|
+
const mode = choice?.mode === 'custom' || choice?.mode === 'live' || choice?.mode === 'anchor' ? choice.mode : this.todayAnchor ? 'anchor' : 'live';
|
|
723
|
+
this.customToday = choice?.customDate || this.customToday;
|
|
724
|
+
this.setToday(mode, this.customToday, false);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
this.write('connection', connectionLog('disconnect', profileName));
|
|
728
|
+
} finally {
|
|
729
|
+
this.connectionBusy = false;
|
|
730
|
+
}
|
|
731
|
+
},
|
|
732
|
+
|
|
733
|
+
async replaceFormSubject(structureUrl, isDev) {
|
|
734
|
+
const current = this.subject;
|
|
735
|
+
const replacement = current.cloneNode(false);
|
|
736
|
+
|
|
737
|
+
replacement.removeAttribute('structure-url');
|
|
738
|
+
if (structureUrl) replacement.setAttribute('structure-url', structureUrl);
|
|
739
|
+
replacement.structureUrl = structureUrl;
|
|
740
|
+
replacement.isDev = isDev;
|
|
741
|
+
if (config.language) replacement.language = this.language;
|
|
742
|
+
if (config.today) replacement.today = this.today;
|
|
743
|
+
if (this.connectionBaseline?.fields) replacement.fields = this.connectionBaseline.fields;
|
|
744
|
+
|
|
745
|
+
current.replaceWith(replacement);
|
|
746
|
+
this.subject = replacement;
|
|
747
|
+
|
|
748
|
+
await customElements.whenDefined(replacement.localName);
|
|
749
|
+
await replacement.componentOnReady?.();
|
|
750
|
+
await config.setup?.(replacement, this);
|
|
751
|
+
this.observe();
|
|
752
|
+
},
|
|
753
|
+
|
|
327
754
|
setOpen(open) {
|
|
328
755
|
this.open = open;
|
|
329
756
|
|
|
@@ -347,13 +774,6 @@ window.harness = function harness(options = {}) {
|
|
|
347
774
|
this.write('theme', theme);
|
|
348
775
|
},
|
|
349
776
|
|
|
350
|
-
setMode(mode) {
|
|
351
|
-
this.mode = mode;
|
|
352
|
-
this.subject.isDev = mode === 'dev';
|
|
353
|
-
|
|
354
|
-
this.write('mode', mode === 'dev' ? 'development · mock data' : `production · ${endpoint?.(this.subject) || 'no endpoint set'}`);
|
|
355
|
-
},
|
|
356
|
-
|
|
357
777
|
setWidth(width) {
|
|
358
778
|
this.width = width;
|
|
359
779
|
|
|
@@ -366,23 +786,6 @@ window.harness = function harness(options = {}) {
|
|
|
366
786
|
|
|
367
787
|
/* ---------- fixtures ---------- */
|
|
368
788
|
|
|
369
|
-
async loadFixtures() {
|
|
370
|
-
let data = {};
|
|
371
|
-
|
|
372
|
-
try {
|
|
373
|
-
data = (await window.loadMockData(config.mocks)) ?? {};
|
|
374
|
-
this.data = data;
|
|
375
|
-
|
|
376
|
-
await apply?.(this.subject, data);
|
|
377
|
-
} catch (error) {
|
|
378
|
-
this.write('fixtures', `failed to load — ${error.message}`);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// Generated from the mock keys, never hand-listed: a hardcoded list drifts
|
|
382
|
-
// the moment someone adds a scenario (R7). Labels only annotate.
|
|
383
|
-
this.setFixtures(Object.keys(data), data);
|
|
384
|
-
},
|
|
385
|
-
|
|
386
789
|
/** Public, so a component that pushes its own mock set can feed the rail. */
|
|
387
790
|
setFixtures(keys, data) {
|
|
388
791
|
if (data) this.data = data;
|
|
@@ -397,10 +800,12 @@ window.harness = function harness(options = {}) {
|
|
|
397
800
|
},
|
|
398
801
|
|
|
399
802
|
run(key) {
|
|
803
|
+
if (this.environmentChanging) return;
|
|
804
|
+
|
|
400
805
|
this.fixture = key;
|
|
401
806
|
this.write('fetch', key === '' ? '(empty)' : key);
|
|
402
807
|
|
|
403
|
-
select?.(this.subject, key, this);
|
|
808
|
+
return key === '' ? clear?.(this.subject, this) : select?.(this.subject, key, this);
|
|
404
809
|
},
|
|
405
810
|
|
|
406
811
|
reload() {
|
|
@@ -587,41 +992,34 @@ const NAV = /* html */ `
|
|
|
587
992
|
`;
|
|
588
993
|
|
|
589
994
|
/*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
* a panel to pick a VIN was the worst thing about the first pass. Everything
|
|
593
|
-
* you set once and forget — language, theme, width, the log — stays in the drawer.
|
|
995
|
+
* Fixtures sit ABOVE the component because they are touched on every interaction.
|
|
996
|
+
* Connection and the other set-once controls stay in the drawer.
|
|
594
997
|
*/
|
|
595
998
|
const BAR = /* html */ `
|
|
596
999
|
<template x-if="show.bar">
|
|
597
1000
|
<div class="card border-base-300 bg-base-100 flex flex-col gap-2 border border-dashed p-3">
|
|
598
1001
|
<div class="flex flex-wrap items-start gap-x-5 gap-y-3">
|
|
599
|
-
<template x-if="show.mode">
|
|
600
|
-
<div class="flex shrink-0 items-center gap-2">
|
|
601
|
-
<span class="eyebrow text-neutral">Mode</span>
|
|
602
|
-
<div class="flex gap-1.5" role="group" aria-label="Mode">
|
|
603
|
-
<template x-for="item in [{ value: 'dev', label: 'Development' }, { value: 'prod', label: 'Production' }]" :key="item.value">
|
|
604
|
-
<button type="button" class="btn btn-xs" :class="mode === item.value ? 'btn-primary' : 'btn-outline'"
|
|
605
|
-
:aria-pressed="mode === item.value" @click="setMode(item.value)" x-text="item.label"></button>
|
|
606
|
-
</template>
|
|
607
|
-
</div>
|
|
608
|
-
</div>
|
|
609
|
-
</template>
|
|
610
|
-
|
|
611
1002
|
<template x-if="show.fixtures">
|
|
612
1003
|
<div class="flex min-w-0 flex-1 flex-wrap items-center gap-2">
|
|
613
1004
|
<span class="eyebrow text-neutral">Fixtures</span>
|
|
614
|
-
<button type="button" class="btn btn-xs btn-outline" @click="reload()">Reload</button>
|
|
1005
|
+
<button type="button" class="btn btn-xs btn-outline" :disabled="connected || environmentChanging" @click="reload()">Reload</button>
|
|
615
1006
|
|
|
616
1007
|
<div class="flex flex-wrap gap-1.5" role="group" aria-label="Fixtures">
|
|
617
1008
|
<template x-for="item in fixtures" :key="item.value">
|
|
618
|
-
<button type="button" class="btn btn-xs font-mono font-normal" :class="fixture === item.value ? 'btn-primary' : 'btn-outline'"
|
|
1009
|
+
<button type="button" class="btn btn-xs font-mono font-normal" :class="fixture === item.value ? 'btn-primary' : 'btn-outline'" :disabled="connected || environmentChanging"
|
|
619
1010
|
:aria-pressed="fixture === item.value" @click="run(item.value)" :title="item.note || item.label">
|
|
620
1011
|
<span x-text="item.label"></span>
|
|
621
1012
|
<span class="font-sans opacity-70" x-show="item.note" x-text="item.note"></span>
|
|
622
1013
|
</button>
|
|
623
1014
|
</template>
|
|
624
1015
|
</div>
|
|
1016
|
+
|
|
1017
|
+
<div
|
|
1018
|
+
class="grid overflow-hidden transition-[grid-template-rows,opacity] duration-[320ms]"
|
|
1019
|
+
:class="connected ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'"
|
|
1020
|
+
>
|
|
1021
|
+
<p class="text-base-content/60 min-h-0 text-xs">Generated fixtures are available again after Disconnect.</p>
|
|
1022
|
+
</div>
|
|
625
1023
|
</div>
|
|
626
1024
|
</template>
|
|
627
1025
|
</div>
|
|
@@ -714,6 +1112,70 @@ const RAIL = /* html */ `
|
|
|
714
1112
|
</div>
|
|
715
1113
|
|
|
716
1114
|
<div class="border-base-300 flex flex-col gap-4 border-t pt-4">
|
|
1115
|
+
<template x-if="show.connection">
|
|
1116
|
+
<div class="flex flex-col gap-2">
|
|
1117
|
+
<span class="eyebrow text-neutral" x-text="'Connection · ' + connectionLabel"></span>
|
|
1118
|
+
|
|
1119
|
+
<div
|
|
1120
|
+
class="grid overflow-hidden transition-[grid-template-rows,opacity] duration-[320ms]"
|
|
1121
|
+
:class="connected ? 'grid-rows-[0fr] opacity-0' : 'grid-rows-[1fr] opacity-100'"
|
|
1122
|
+
:aria-hidden="connected ? 'true' : 'false'"
|
|
1123
|
+
:inert="connected"
|
|
1124
|
+
>
|
|
1125
|
+
<div class="min-h-0">
|
|
1126
|
+
<div class="flex flex-col gap-2">
|
|
1127
|
+
<template x-for="field in connectionFields" :key="field.name">
|
|
1128
|
+
<label class="flex flex-col gap-1">
|
|
1129
|
+
<span class="text-base-content/70 text-xs font-medium" x-text="field.label"></span>
|
|
1130
|
+
<input
|
|
1131
|
+
class="input input-sm input-bordered w-full font-mono text-xs"
|
|
1132
|
+
:type="field.inputType"
|
|
1133
|
+
:name="'connection-' + field.name"
|
|
1134
|
+
:placeholder="field.placeholder"
|
|
1135
|
+
:autocomplete="field.secret ? 'new-password' : 'off'"
|
|
1136
|
+
spellcheck="false"
|
|
1137
|
+
x-model="connectionDraft[field.name]"
|
|
1138
|
+
:disabled="connected || connectionBusy"
|
|
1139
|
+
@input="clearConnectionError(field.name)"
|
|
1140
|
+
/>
|
|
1141
|
+
<div
|
|
1142
|
+
class="grid overflow-hidden transition-[grid-template-rows,opacity] duration-[320ms]"
|
|
1143
|
+
:class="connectionErrors[field.name] ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'"
|
|
1144
|
+
>
|
|
1145
|
+
<p class="text-error min-h-0 text-xs" x-text="connectionErrors[field.name]"></p>
|
|
1146
|
+
</div>
|
|
1147
|
+
</label>
|
|
1148
|
+
</template>
|
|
1149
|
+
|
|
1150
|
+
<div
|
|
1151
|
+
class="grid overflow-hidden transition-[grid-template-rows,opacity] duration-[320ms]"
|
|
1152
|
+
:class="connectionError ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'"
|
|
1153
|
+
>
|
|
1154
|
+
<p class="text-error min-h-0 text-xs" x-text="connectionError"></p>
|
|
1155
|
+
</div>
|
|
1156
|
+
|
|
1157
|
+
<p class="text-base-content/60 text-xs">Kept only in this tab’s session storage. Nothing is added to the page URL or event log.</p>
|
|
1158
|
+
<button type="button" class="btn btn-sm btn-primary" :disabled="connectionBusy" @click="connect()">Connect to live API</button>
|
|
1159
|
+
</div>
|
|
1160
|
+
</div>
|
|
1161
|
+
</div>
|
|
1162
|
+
|
|
1163
|
+
<div
|
|
1164
|
+
class="grid overflow-hidden transition-[grid-template-rows,opacity] duration-[320ms]"
|
|
1165
|
+
:class="connected ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'"
|
|
1166
|
+
:aria-hidden="connected ? 'false' : 'true'"
|
|
1167
|
+
:inert="!connected"
|
|
1168
|
+
>
|
|
1169
|
+
<div class="min-h-0">
|
|
1170
|
+
<div class="flex flex-col gap-2">
|
|
1171
|
+
<p class="text-base-content/70 text-xs">Live settings are active. Their values stay masked and are never logged.</p>
|
|
1172
|
+
<button type="button" class="btn btn-sm btn-outline" :disabled="connectionBusy" @click="disconnect()">Disconnect</button>
|
|
1173
|
+
</div>
|
|
1174
|
+
</div>
|
|
1175
|
+
</div>
|
|
1176
|
+
</div>
|
|
1177
|
+
</template>
|
|
1178
|
+
|
|
717
1179
|
<template x-if="show.language">
|
|
718
1180
|
<div class="flex flex-col gap-1.5">
|
|
719
1181
|
<span class="eyebrow text-neutral" x-text="'Language · ' + dir.toUpperCase()"></span>
|
|
@@ -726,6 +1188,71 @@ const RAIL = /* html */ `
|
|
|
726
1188
|
</div>
|
|
727
1189
|
</template>
|
|
728
1190
|
|
|
1191
|
+
<template x-if="show.environment">
|
|
1192
|
+
<div class="flex flex-col gap-1.5">
|
|
1193
|
+
<span class="eyebrow text-neutral" x-text="'Environment · ' + (environmentLabel || 'Unavailable')"></span>
|
|
1194
|
+
<label>
|
|
1195
|
+
<span class="sr-only">Environment</span>
|
|
1196
|
+
<select
|
|
1197
|
+
class="select select-sm select-bordered w-full font-mono"
|
|
1198
|
+
aria-label="Environment"
|
|
1199
|
+
:value="environment"
|
|
1200
|
+
:disabled="connected || environmentChanging || !environments.length"
|
|
1201
|
+
:title="connected ? 'Disconnect to switch generated environments.' : ''"
|
|
1202
|
+
@change="setEnvironment($event.target.value)"
|
|
1203
|
+
>
|
|
1204
|
+
<template x-for="item in environments" :key="item.name">
|
|
1205
|
+
<option :value="item.name" x-text="item.label"></option>
|
|
1206
|
+
</template>
|
|
1207
|
+
</select>
|
|
1208
|
+
</label>
|
|
1209
|
+
<p class="text-base-content/60 text-xs" x-show="environmentChanging">Loading generated fixtures…</p>
|
|
1210
|
+
<div
|
|
1211
|
+
class="grid overflow-hidden transition-[grid-template-rows,opacity] duration-[320ms]"
|
|
1212
|
+
:class="connected ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'"
|
|
1213
|
+
>
|
|
1214
|
+
<p class="text-base-content/60 min-h-0 text-xs">Disconnect to switch generated environments.</p>
|
|
1215
|
+
</div>
|
|
1216
|
+
<p class="text-error text-xs" x-show="environmentError" x-text="environmentError"></p>
|
|
1217
|
+
</div>
|
|
1218
|
+
</template>
|
|
1219
|
+
|
|
1220
|
+
<template x-if="show.today">
|
|
1221
|
+
<div class="flex flex-col gap-1.5">
|
|
1222
|
+
<span class="eyebrow text-neutral" x-text="'Today · ' + todayLabel"></span>
|
|
1223
|
+
<div class="flex flex-wrap gap-1.5" role="group" aria-label="Today">
|
|
1224
|
+
<button type="button" class="btn btn-sm" :class="todayMode === 'anchor' ? 'btn-primary' : 'btn-outline'"
|
|
1225
|
+
:aria-pressed="todayMode === 'anchor'" :disabled="!canUseToday('anchor')" :title="connected ? liveTodayExplanation : (todayAnchor ? 'Fixture anchor · ' + todayAnchor : 'No generated environment selected')"
|
|
1226
|
+
@click="setToday('anchor')">Anchor</button>
|
|
1227
|
+
<button type="button" class="btn btn-sm" :class="todayMode === 'live' ? 'btn-primary' : 'btn-outline'"
|
|
1228
|
+
:aria-pressed="todayMode === 'live'" @click="setToday('live')">Live</button>
|
|
1229
|
+
<button type="button" class="btn btn-sm" :class="todayMode === 'custom' ? 'btn-primary' : 'btn-outline'"
|
|
1230
|
+
:aria-pressed="todayMode === 'custom'" :disabled="!canUseToday('custom')" :title="connected ? liveTodayExplanation : ''" @click="setToday('custom')">Custom</button>
|
|
1231
|
+
</div>
|
|
1232
|
+
|
|
1233
|
+
<div
|
|
1234
|
+
class="grid overflow-hidden transition-[grid-template-rows,opacity] duration-200"
|
|
1235
|
+
:class="connected ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'"
|
|
1236
|
+
>
|
|
1237
|
+
<p class="text-base-content/60 min-h-0 text-xs" x-text="liveTodayExplanation"></p>
|
|
1238
|
+
</div>
|
|
1239
|
+
|
|
1240
|
+
<div
|
|
1241
|
+
class="grid overflow-hidden transition-[grid-template-rows,opacity] duration-200"
|
|
1242
|
+
:class="todayMode === 'custom' && !connected ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'"
|
|
1243
|
+
:aria-hidden="todayMode === 'custom' && !connected ? 'false' : 'true'"
|
|
1244
|
+
>
|
|
1245
|
+
<div class="min-h-0">
|
|
1246
|
+
<label class="mt-1 flex flex-col gap-1">
|
|
1247
|
+
<span class="sr-only">Custom today</span>
|
|
1248
|
+
<input class="input input-sm input-bordered w-full" type="date" x-model="customToday" :disabled="connected || todayMode !== 'custom'" @change="setToday('custom', customToday)" />
|
|
1249
|
+
</label>
|
|
1250
|
+
<p class="text-base-content/60 mt-1 text-xs" x-text="todayAnchor ? 'Display only — statuses were computed at ' + todayAnchor : 'Display only — fixture statuses are not recomputed'"></p>
|
|
1251
|
+
</div>
|
|
1252
|
+
</div>
|
|
1253
|
+
</div>
|
|
1254
|
+
</template>
|
|
1255
|
+
|
|
729
1256
|
<template x-if="show.theme">
|
|
730
1257
|
<div class="flex flex-col gap-1.5">
|
|
731
1258
|
<span class="eyebrow text-neutral">Theme</span>
|