@cyberskill/design 1.1.1 → 1.3.8
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/DESIGN.md +28 -5
- package/README.md +23 -22
- package/SKILL.md +7 -7
- package/THIRD-PARTY-NOTICES.md +35 -0
- package/VERSION +1 -1
- package/_ds_bundle.js +1495 -1733
- package/_ds_manifest.json +1 -1
- package/_esm/cs.mjs +18 -4
- package/_esm/react.d.ts +2 -0
- package/_esm/react.mjs +7 -1
- package/_vendor/NOTICE.md +16 -0
- package/_vendor/babel/README.md +7 -0
- package/_vendor/babel/babel.min.js +4 -0
- package/_vendor/react/README.md +3 -0
- package/_vendor/react/react-dom.production.min.js +1 -0
- package/_vendor/react/react.production.min.js +1 -0
- package/assets/aurora-hoa.webp +0 -0
- package/assets/aurora-kim.webp +0 -0
- package/assets/aurora-moc.webp +0 -0
- package/assets/aurora-tho.webp +0 -0
- package/assets/aurora-thuy.webp +0 -0
- package/base/a11y.css +18 -0
- package/base/ai.css +9 -4
- package/base/collections.css +18 -7
- package/base/components.css +16 -4
- package/base/controls.css +116 -66
- package/base/data.css +4 -4
- package/base/feedback.css +14 -2
- package/base/forms.css +10 -4
- package/base/glass.css +7 -1
- package/base/interaction.css +6 -2
- package/base/navigation.css +9 -3
- package/base/reset.css +7 -1
- package/base/responsive.css +38 -12
- package/base/shell.css +15 -3
- package/components/_i18n/i18n.js +41 -4
- package/components/_i18n/strings.js +89 -22
- package/components/ai/ChatMessage.d.ts +2 -0
- package/components/ai/ChatMessage.jsx +8 -4
- package/components/ai/ConfidenceMeter.d.ts +2 -0
- package/components/ai/ConfidenceMeter.jsx +8 -6
- package/components/ai/HumanReviewGate.d.ts +2 -0
- package/components/ai/PromptInput.d.ts +2 -0
- package/components/ai/TypingIndicator.d.ts +2 -0
- package/components/ai/ai-conversation.card.html +3 -3
- package/components/ai/ai-lumi.card.html +3 -3
- package/components/ai/ai.card.html +3 -3
- package/components/brand/brand.card.html +3 -3
- package/components/button/buttons.card.html +3 -3
- package/components/data/Image.jsx +18 -2
- package/components/data/Sortable.d.ts +5 -1
- package/components/data/Sortable.jsx +42 -9
- package/components/data/Sortable.prompt.md +4 -2
- package/components/data/Terminal.jsx +3 -2
- package/components/data/Tooltip.d.ts +2 -0
- package/components/data/Tooltip.jsx +6 -3
- package/components/data/Tree.d.ts +2 -1
- package/components/data/Tree.jsx +137 -16
- package/components/data/Tree.prompt.md +1 -1
- package/components/data/Watermark.jsx +11 -3
- package/components/data/collections.card.html +3 -3
- package/components/data/data.card.html +3 -3
- package/components/datatable/DataGrid.jsx +10 -1
- package/components/datatable/DataTable.d.ts +24 -1
- package/components/datatable/DataTable.jsx +78 -5
- package/components/datatable/DataTable.prompt.md +2 -1
- package/components/datatable/datatable.card.html +20 -16
- package/components/dialog/Dialog.jsx +13 -45
- package/components/dialog/dialog.card.html +3 -3
- package/components/feedback/Alert.d.ts +2 -0
- package/components/feedback/Alert.jsx +8 -2
- package/components/feedback/EmptyState.d.ts +2 -0
- package/components/feedback/EmptyState.jsx +6 -3
- package/components/feedback/ProgressBar.d.ts +2 -0
- package/components/feedback/ProgressBar.jsx +9 -4
- package/components/feedback/Toast.jsx +15 -1
- package/components/feedback/Toast.prompt.md +2 -1
- package/components/feedback/feedback-2.card.html +3 -3
- package/components/feedback/feedback.card.html +3 -3
- package/components/forms/Cascader.jsx +76 -8
- package/components/forms/Editor.jsx +37 -2
- package/components/forms/FileUpload.d.ts +2 -0
- package/components/forms/FileUpload.jsx +22 -8
- package/components/forms/Form.d.ts +3 -1
- package/components/forms/Form.jsx +9 -1
- package/components/forms/Form.prompt.md +1 -1
- package/components/forms/Mentions.d.ts +1 -1
- package/components/forms/Mentions.jsx +59 -7
- package/components/forms/Mentions.prompt.md +3 -1
- package/components/forms/Rating.d.ts +3 -2
- package/components/forms/Rating.jsx +34 -3
- package/components/forms/Rating.prompt.md +1 -1
- package/components/forms/Select.d.ts +2 -0
- package/components/forms/Select.jsx +6 -2
- package/components/forms/Slider.d.ts +2 -0
- package/components/forms/Slider.jsx +5 -2
- package/components/forms/Switch.d.ts +2 -0
- package/components/forms/Switch.jsx +15 -3
- package/components/forms/TimePicker.jsx +3 -1
- package/components/forms/Toggle.d.ts +2 -0
- package/components/forms/Toggle.jsx +14 -2
- package/components/forms/forms-2.card.html +3 -3
- package/components/forms/forms.card.html +3 -3
- package/components/icon/Icon.d.ts +1 -1
- package/components/icon/Icon.jsx +1 -0
- package/components/icon/Icon.prompt.md +1 -1
- package/components/icon/icon.card.html +3 -3
- package/components/logo/logo.card.html +3 -3
- package/components/navigation/CommandPalette.d.ts +2 -0
- package/components/navigation/CommandPalette.jsx +22 -7
- package/components/navigation/Menu.d.ts +2 -0
- package/components/navigation/Menu.jsx +60 -6
- package/components/navigation/Steps.d.ts +2 -0
- package/components/navigation/Steps.jsx +6 -3
- package/components/navigation/Tabs.d.ts +2 -0
- package/components/navigation/Tabs.jsx +6 -3
- package/components/navigation/Toolbar.d.ts +3 -2
- package/components/navigation/Toolbar.jsx +119 -12
- package/components/navigation/Toolbar.prompt.md +1 -1
- package/components/navigation/navigation.card.html +3 -3
- package/components/navigation/shell.card.html +3 -3
- package/components/overlays/AlertDialog.jsx +19 -49
- package/components/overlays/ContextMenu.d.ts +2 -0
- package/components/overlays/ContextMenu.jsx +6 -3
- package/components/overlays/Drawer.d.ts +2 -0
- package/components/overlays/Drawer.jsx +24 -20
- package/components/overlays/OverlayManager.d.ts +40 -0
- package/components/overlays/OverlayManager.jsx +214 -0
- package/components/overlays/OverlayManager.prompt.md +12 -0
- package/components/overlays/Tour.jsx +14 -7
- package/components/overlays/alertdialog.card.html +3 -3
- package/components/overlays/overlays.card.html +3 -3
- package/components/textfield/textfield.card.html +3 -3
- package/dist/styles.min.css +2252 -0
- package/docs/benchmark-rubric.md +1 -1
- package/docs/ci-cd.md +19 -12
- package/docs/consumer-grant.md +3 -0
- package/docs/consuming.md +13 -13
- package/docs/contrast-report.md +79 -1
- package/docs/conventions.md +21 -8
- package/docs/decisions.md +45 -7
- package/docs/deploy.md +17 -6
- package/docs/design-styles.md +2 -2
- package/docs/quality-gates.md +35 -15
- package/docs/release-notes.md +2 -2
- package/docs/release-runbook.md +78 -0
- package/docs/sync.md +2 -2
- package/docs/vi/benchmark-rubric.md +1 -1
- package/docs/vi/ci-cd.md +17 -12
- package/docs/vi/consumer-grant.md +3 -0
- package/docs/vi/consuming.md +13 -13
- package/docs/vi/contrast-report.md +79 -1
- package/docs/vi/conventions.md +20 -7
- package/docs/vi/decisions.md +43 -6
- package/docs/vi/deploy.md +17 -6
- package/docs/vi/quality-gates.md +34 -15
- package/docs/vi/release-notes.md +2 -2
- package/docs/vi/release-runbook.md +78 -0
- package/docs/vi/sync.md +2 -2
- package/docs/viewer.html +2 -2
- package/fonts/OFL.txt +98 -0
- package/guidelines/atomic-view.html +13 -9
- package/guidelines/brand-imagery.html +1 -1
- package/guidelines/elements-variants.html +5 -5
- package/guidelines/spacing-breakpoints.html +2 -1
- package/guidelines/surfaces-glass.html +1 -1
- package/llms.txt +5 -5
- package/package.json +38 -10
- package/templates/_ds-base.canonical.js +55 -0
- package/templates/ai-cluster-demo.html +2 -2
- package/templates/app-shell/AppShell.dc.html +7 -5
- package/templates/app-shell/content-schema.json +7 -0
- package/templates/app-shell/ds-base.js +33 -1
- package/templates/app-shell/support.js +13 -20
- package/templates/article/Article.dc.html +7 -3
- package/templates/article/content-schema.json +7 -0
- package/templates/article/ds-base.js +33 -1
- package/templates/article/support.js +13 -20
- package/templates/auth/Auth.dc.html +33 -12
- package/templates/auth/content-schema.json +37 -0
- package/templates/auth/ds-base.js +33 -1
- package/templates/auth/support.js +13 -20
- package/templates/bod-deck/BodDeck.dc.html +11 -10
- package/templates/bod-deck/ds-base.js +33 -1
- package/templates/bod-deck/support.js +13 -20
- package/templates/bod-investor-update/BodInvestorUpdate.dc.html +4 -3
- package/templates/bod-investor-update/ds-base.js +33 -1
- package/templates/bod-investor-update/support.js +13 -20
- package/templates/bod-memo/BodMemo.dc.html +6 -5
- package/templates/bod-memo/ds-base.js +33 -1
- package/templates/bod-memo/support.js +13 -20
- package/templates/bod-minutes/BodMinutes.dc.html +2 -1
- package/templates/bod-minutes/ds-base.js +33 -1
- package/templates/bod-minutes/support.js +13 -20
- package/templates/bod-report/BodReport.dc.html +3 -2
- package/templates/bod-report/ds-base.js +33 -1
- package/templates/bod-report/support.js +13 -20
- package/templates/bod-resolution/BodResolution.dc.html +5 -4
- package/templates/bod-resolution/ds-base.js +33 -1
- package/templates/bod-resolution/support.js +13 -20
- package/templates/culture-event-invite/CultureEventInvite.dc.html +3 -2
- package/templates/culture-event-invite/ds-base.js +33 -1
- package/templates/culture-event-invite/support.js +13 -20
- package/templates/dashboard/Dashboard.dc.html +10 -6
- package/templates/dashboard/content-schema.json +7 -0
- package/templates/dashboard/ds-base.js +33 -1
- package/templates/dashboard/support.js +13 -20
- package/templates/delivery-change-note/DeliveryChangeNote.dc.html +4 -3
- package/templates/delivery-change-note/ds-base.js +33 -1
- package/templates/delivery-change-note/support.js +13 -20
- package/templates/delivery-kickoff/DeliveryKickoff.dc.html +3 -2
- package/templates/delivery-kickoff/ds-base.js +33 -1
- package/templates/delivery-kickoff/support.js +13 -20
- package/templates/delivery-qbr-deck/DeliveryQbrDeck.dc.html +6 -5
- package/templates/delivery-qbr-deck/ds-base.js +33 -1
- package/templates/delivery-qbr-deck/support.js +13 -20
- package/templates/delivery-runbook/DeliveryRunbook.dc.html +5 -4
- package/templates/delivery-runbook/ds-base.js +33 -1
- package/templates/delivery-runbook/support.js +13 -20
- package/templates/delivery-status-email/DeliveryStatusEmail.dc.html +3 -2
- package/templates/delivery-status-email/ds-base.js +33 -1
- package/templates/delivery-status-email/support.js +13 -20
- package/templates/doc-style-guide/DocStyleGuide.dc.html +67 -64
- package/templates/doc-style-guide/ds-base.js +33 -1
- package/templates/doc-style-guide/support.js +13 -20
- package/templates/doc-suite-index/DocSuiteIndex.dc.html +46 -45
- package/templates/doc-suite-index/ds-base.js +33 -1
- package/templates/doc-suite-index/support.js +13 -20
- package/templates/doc-templates/DocTemplates.dc.html +42 -41
- package/templates/doc-templates/ds-base.js +33 -1
- package/templates/doc-templates/support.js +13 -20
- package/templates/email/Email.dc.html +3 -2
- package/templates/email/ds-base.js +33 -1
- package/templates/email/support.js +13 -20
- package/templates/email-safe/email-announcement.html +2 -2
- package/templates/email-safe/email-dunning.html +2 -2
- package/templates/email-safe/email-investor.html +2 -2
- package/templates/email-safe/email-launch.html +2 -2
- package/templates/email-safe/email-newsletter.html +2 -2
- package/templates/email-safe/email-status.html +2 -2
- package/templates/email-safe/email-transactional.html +2 -2
- package/templates/finance-dunning-email/FinanceDunningEmail.dc.html +6 -5
- package/templates/finance-dunning-email/ds-base.js +33 -1
- package/templates/finance-dunning-email/support.js +13 -20
- package/templates/finance-expense-report/FinanceExpenseReport.dc.html +4 -3
- package/templates/finance-expense-report/ds-base.js +33 -1
- package/templates/finance-expense-report/support.js +13 -20
- package/templates/finance-invoice/FinanceInvoice.dc.html +6 -5
- package/templates/finance-invoice/ds-base.js +33 -1
- package/templates/finance-invoice/support.js +13 -20
- package/templates/finance-quote/FinanceQuote.dc.html +6 -5
- package/templates/finance-quote/ds-base.js +33 -1
- package/templates/finance-quote/support.js +13 -20
- package/templates/hr-announcement/HrAnnouncement.dc.html +5 -4
- package/templates/hr-announcement/ds-base.js +33 -1
- package/templates/hr-announcement/support.js +13 -20
- package/templates/hr-interview-kit/HrInterviewKit.dc.html +5 -4
- package/templates/hr-interview-kit/ds-base.js +33 -1
- package/templates/hr-interview-kit/support.js +13 -20
- package/templates/hr-offboarding/HrOffboarding.dc.html +2 -1
- package/templates/hr-offboarding/ds-base.js +33 -1
- package/templates/hr-offboarding/support.js +13 -20
- package/templates/hr-performance-review/HrPerformanceReview.dc.html +2 -1
- package/templates/hr-performance-review/ds-base.js +33 -1
- package/templates/hr-performance-review/support.js +13 -20
- package/templates/hr-pip/HrPip.dc.html +2 -1
- package/templates/hr-pip/ds-base.js +33 -1
- package/templates/hr-pip/support.js +13 -20
- package/templates/kitchen-sink.html +9 -4
- package/templates/legal-msa/LegalMsa.dc.html +2 -1
- package/templates/legal-msa/ds-base.js +33 -1
- package/templates/legal-msa/support.js +13 -20
- package/templates/legal-sow/LegalSow.dc.html +2 -1
- package/templates/legal-sow/ds-base.js +33 -1
- package/templates/legal-sow/support.js +13 -20
- package/templates/marketing-campaign-brief/MarketingCampaignBrief.dc.html +3 -2
- package/templates/marketing-campaign-brief/ds-base.js +33 -1
- package/templates/marketing-campaign-brief/support.js +13 -20
- package/templates/marketing-case-study/MarketingCaseStudy.dc.html +6 -5
- package/templates/marketing-case-study/ds-base.js +33 -1
- package/templates/marketing-case-study/support.js +13 -20
- package/templates/marketing-launch/MarketingLaunch.dc.html +6 -5
- package/templates/marketing-launch/ds-base.js +33 -1
- package/templates/marketing-launch/support.js +13 -20
- package/templates/marketing-newsletter/MarketingNewsletter.dc.html +13 -12
- package/templates/marketing-newsletter/ds-base.js +33 -1
- package/templates/marketing-newsletter/support.js +13 -20
- package/templates/marketing-page/MarketingPage.dc.html +19 -14
- package/templates/marketing-page/content-schema.json +1 -0
- package/templates/marketing-page/ds-base.js +33 -1
- package/templates/marketing-page/support.js +13 -20
- package/templates/marketing-press-release/MarketingPressRelease.dc.html +2 -1
- package/templates/marketing-press-release/ds-base.js +33 -1
- package/templates/marketing-press-release/support.js +13 -20
- package/templates/marketing-social-kit/MarketingSocialKit.dc.html +5 -4
- package/templates/marketing-social-kit/ds-base.js +33 -1
- package/templates/marketing-social-kit/support.js +13 -20
- package/templates/sales-one-pager/SalesOnePager.dc.html +5 -4
- package/templates/sales-one-pager/ds-base.js +33 -1
- package/templates/sales-one-pager/support.js +13 -20
- package/templates/sales-proposal-deck/SalesProposalDeck.dc.html +7 -6
- package/templates/sales-proposal-deck/ds-base.js +33 -1
- package/templates/sales-proposal-deck/support.js +13 -20
- package/templates/settings/Settings.dc.html +7 -3
- package/templates/settings/content-schema.json +7 -0
- package/templates/settings/ds-base.js +33 -1
- package/templates/settings/support.js +13 -20
- package/templates/slide-deck/SlideDeck.dc.html +5 -4
- package/templates/slide-deck/ds-base.js +33 -1
- package/templates/slide-deck/support.js +13 -20
- package/templates/team-meeting-agenda/TeamMeetingAgenda.dc.html +2 -1
- package/templates/team-meeting-agenda/ds-base.js +33 -1
- package/templates/team-meeting-agenda/support.js +13 -20
- package/templates/tech-incident-report/TechIncidentReport.dc.html +3 -2
- package/templates/tech-incident-report/ds-base.js +33 -1
- package/templates/tech-incident-report/support.js +13 -20
- package/templates/tech-release-notes/TechReleaseNotes.dc.html +6 -5
- package/templates/tech-release-notes/ds-base.js +33 -1
- package/templates/tech-release-notes/support.js +13 -20
- package/templates/tech-retro/TechRetro.dc.html +4 -3
- package/templates/tech-retro/ds-base.js +33 -1
- package/templates/tech-retro/support.js +13 -20
- package/templates/tech-rfc/TechRfc.dc.html +3 -2
- package/templates/tech-rfc/ds-base.js +33 -1
- package/templates/tech-rfc/support.js +13 -20
- package/templates/vn-appointment-transfer/VnAppointmentTransfer.dc.html +36 -35
- package/templates/vn-appointment-transfer/ds-base.js +33 -1
- package/templates/vn-appointment-transfer/support.js +13 -20
- package/templates/vn-certificate-of-employment/VnCertificateOfEmployment.dc.html +27 -26
- package/templates/vn-certificate-of-employment/ds-base.js +33 -1
- package/templates/vn-certificate-of-employment/support.js +13 -20
- package/templates/vn-code-of-conduct/VnCodeOfConduct.dc.html +44 -43
- package/templates/vn-code-of-conduct/ds-base.js +33 -1
- package/templates/vn-code-of-conduct/support.js +13 -20
- package/templates/vn-compensation-regulation/VnCompensationRegulation.dc.html +53 -52
- package/templates/vn-compensation-regulation/ds-base.js +33 -1
- package/templates/vn-compensation-regulation/support.js +13 -20
- package/templates/vn-contract-amendment/VnContractAmendment.dc.html +41 -40
- package/templates/vn-contract-amendment/ds-base.js +33 -1
- package/templates/vn-contract-amendment/support.js +13 -20
- package/templates/vn-contractor-agreement/VnContractorAgreement.dc.html +50 -49
- package/templates/vn-contractor-agreement/ds-base.js +33 -1
- package/templates/vn-contractor-agreement/support.js +13 -20
- package/templates/vn-data-protection-policy/VnDataProtectionPolicy.dc.html +54 -53
- package/templates/vn-data-protection-policy/ds-base.js +33 -1
- package/templates/vn-data-protection-policy/support.js +13 -20
- package/templates/vn-disciplinary-case-file/VnDisciplinaryCaseFile.dc.html +72 -71
- package/templates/vn-disciplinary-case-file/ds-base.js +33 -1
- package/templates/vn-disciplinary-case-file/support.js +13 -20
- package/templates/vn-disciplinary-schedule/VnDisciplinarySchedule.dc.html +21 -20
- package/templates/vn-disciplinary-schedule/ds-base.js +33 -1
- package/templates/vn-disciplinary-schedule/support.js +13 -20
- package/templates/vn-employee-request/VnEmployeeRequest.dc.html +54 -53
- package/templates/vn-employee-request/ds-base.js +33 -1
- package/templates/vn-employee-request/support.js +13 -20
- package/templates/vn-exit-handover/VnExitHandover.dc.html +122 -121
- package/templates/vn-exit-handover/ds-base.js +33 -1
- package/templates/vn-exit-handover/support.js +13 -20
- package/templates/vn-foreign-employee-pack/VnForeignEmployeePack.dc.html +31 -30
- package/templates/vn-foreign-employee-pack/ds-base.js +33 -1
- package/templates/vn-foreign-employee-pack/support.js +13 -20
- package/templates/vn-grassroots-democracy/VnGrassrootsDemocracy.dc.html +54 -53
- package/templates/vn-grassroots-democracy/ds-base.js +33 -1
- package/templates/vn-grassroots-democracy/support.js +13 -20
- package/templates/vn-infosec-policy/VnInfosecPolicy.dc.html +50 -49
- package/templates/vn-infosec-policy/ds-base.js +33 -1
- package/templates/vn-infosec-policy/support.js +13 -20
- package/templates/vn-internal-labor-regulations/VnInternalLaborRegulations.dc.html +84 -83
- package/templates/vn-internal-labor-regulations/ds-base.js +33 -1
- package/templates/vn-internal-labor-regulations/support.js +13 -20
- package/templates/vn-internship-agreement/VnInternshipAgreement.dc.html +44 -43
- package/templates/vn-internship-agreement/ds-base.js +33 -1
- package/templates/vn-internship-agreement/support.js +13 -20
- package/templates/vn-job-description/VnJobDescription.dc.html +28 -27
- package/templates/vn-job-description/ds-base.js +33 -1
- package/templates/vn-job-description/support.js +13 -20
- package/templates/vn-labor-contract/VnLaborContract.dc.html +109 -108
- package/templates/vn-labor-contract/ds-base.js +33 -1
- package/templates/vn-labor-contract/support.js +13 -20
- package/templates/vn-labour-management-book/VnLabourManagementBook.dc.html +32 -31
- package/templates/vn-labour-management-book/ds-base.js +33 -1
- package/templates/vn-labour-management-book/support.js +13 -20
- package/templates/vn-mutual-nda/VnMutualNda.dc.html +45 -44
- package/templates/vn-mutual-nda/ds-base.js +33 -1
- package/templates/vn-mutual-nda/support.js +13 -20
- package/templates/vn-ndnca-ip/VnNdncaIp.dc.html +73 -72
- package/templates/vn-ndnca-ip/ds-base.js +33 -1
- package/templates/vn-ndnca-ip/support.js +13 -20
- package/templates/vn-offer-letter/VnOfferLetter.dc.html +32 -31
- package/templates/vn-offer-letter/ds-base.js +33 -1
- package/templates/vn-offer-letter/support.js +13 -20
- package/templates/vn-onboarding-checklist/VnOnboardingChecklist.dc.html +16 -15
- package/templates/vn-onboarding-checklist/ds-base.js +33 -1
- package/templates/vn-onboarding-checklist/support.js +13 -20
- package/templates/vn-pdpl-consent/VnPdplConsent.dc.html +43 -42
- package/templates/vn-pdpl-consent/ds-base.js +33 -1
- package/templates/vn-pdpl-consent/support.js +13 -20
- package/templates/vn-performance-evaluation-regulation/VnPerformanceEvaluationRegulation.dc.html +65 -64
- package/templates/vn-performance-evaluation-regulation/ds-base.js +33 -1
- package/templates/vn-performance-evaluation-regulation/support.js +13 -20
- package/templates/vn-performance-review-form/VnPerformanceReviewForm.dc.html +49 -48
- package/templates/vn-performance-review-form/ds-base.js +33 -1
- package/templates/vn-performance-review-form/support.js +13 -20
- package/templates/vn-phantom-stock/VnPhantomStock.dc.html +41 -40
- package/templates/vn-phantom-stock/ds-base.js +33 -1
- package/templates/vn-phantom-stock/support.js +13 -20
- package/templates/vn-probation-contract/VnProbationContract.dc.html +56 -55
- package/templates/vn-probation-contract/ds-base.js +33 -1
- package/templates/vn-probation-contract/support.js +13 -20
- package/templates/vn-receipt-acknowledgement/VnReceiptAcknowledgement.dc.html +28 -27
- package/templates/vn-receipt-acknowledgement/ds-base.js +33 -1
- package/templates/vn-receipt-acknowledgement/support.js +13 -20
- package/templates/vn-remote-work-policy/VnRemoteWorkPolicy.dc.html +44 -43
- package/templates/vn-remote-work-policy/ds-base.js +33 -1
- package/templates/vn-remote-work-policy/support.js +13 -20
- package/templates/vn-resignation-letter/VnResignationLetter.dc.html +20 -19
- package/templates/vn-resignation-letter/ds-base.js +33 -1
- package/templates/vn-resignation-letter/support.js +13 -20
- package/templates/vn-salary-scale/VnSalaryScale.dc.html +39 -38
- package/templates/vn-salary-scale/ds-base.js +33 -1
- package/templates/vn-salary-scale/support.js +13 -20
- package/templates/vn-sow-appendix/VnSowAppendix.dc.html +21 -20
- package/templates/vn-sow-appendix/ds-base.js +33 -1
- package/templates/vn-sow-appendix/support.js +13 -20
- package/templates/vn-termination-decision/VnTerminationDecision.dc.html +25 -24
- package/templates/vn-termination-decision/ds-base.js +33 -1
- package/templates/vn-termination-decision/support.js +13 -20
- package/templates/vn-total-rewards-appendix/VnTotalRewardsAppendix.dc.html +63 -62
- package/templates/vn-total-rewards-appendix/ds-base.js +33 -1
- package/templates/vn-total-rewards-appendix/support.js +13 -20
- package/templates/vn-training-commitment/VnTrainingCommitment.dc.html +39 -38
- package/templates/vn-training-commitment/ds-base.js +33 -1
- package/templates/vn-training-commitment/support.js +13 -20
- package/templates/vn-travel-expense-policy/VnTravelExpensePolicy.dc.html +50 -49
- package/templates/vn-travel-expense-policy/ds-base.js +33 -1
- package/templates/vn-travel-expense-policy/support.js +13 -20
- package/tokens/colors.css +19 -1
- package/tokens/component-tokens.css +1 -0
- package/tokens/element-seeds.json +2 -2
- package/tokens/elements.css +228 -21
- package/tokens/elevation.css +8 -2
- package/tokens/native/CSTokens.kt +37 -2
- package/tokens/native/CSTokens.swift +37 -2
- package/tokens/native/cs_tokens.dart +37 -2
- package/tokens/provenance.json +12 -12
- package/tokens/spacing.css +4 -1
- package/tokens/tokens.dtcg.json +129 -16
- package/tokens/tokens.js +59 -18
- package/tokens/tokens.json +58 -17
- package/tokens/typography.css +2 -0
- package/ui_kits/deck/index.html +4 -0
- package/ui_kits/status-hub/StatusHub.jsx +30 -4
- package/ui_kits/status-hub/index.html +3 -3
- package/ui_kits/status-hub/login.html +55 -9
- package/ui_kits/status-hub/project.html +4 -0
- package/ui_kits/status-hub/settings.html +35 -13
- package/ui_kits/status-hub/status.css +5 -1
- package/ui_kits/website/Website.jsx +25 -3
- package/ui_kits/website/careers.html +5 -1
- package/ui_kits/website/chat.html +5 -3
- package/ui_kits/website/index.html +3 -3
- package/ui_kits/website/site.css +3 -3
- package/ui_kits/website/work.html +5 -1
- package/assets/aurora-hoa.png +0 -0
- package/assets/aurora-kim.png +0 -0
- package/assets/aurora-moc.png +0 -0
- package/assets/aurora-thuy.png +0 -0
- package/docs/status/assets/favicon.svg +0 -5
- package/docs/status/assets/status-legacy.css +0 -399
- package/docs/status/assets/status-legacy.js +0 -505
- package/docs/status/assets/status.css +0 -644
- package/docs/status/assets/status.js +0 -1308
- package/docs/status/data/status-feed.json +0 -1
- package/docs/status/data/task/TASK-REL-001.js +0 -1
- package/docs/status/data/task/TASK-REL-002.js +0 -1
- package/docs/status/index.html +0 -42
- package/docs/status/roadmap.html +0 -4
- package/docs/status/status-legacy.html +0 -117
- package/docs/tasks/BACKLOG.md +0 -26
- package/docs/tasks/release/TASK-REL-001-launch-1-1-0/spec.md +0 -55
- package/docs/tasks/release/TASK-REL-002-republish-1-1-1/spec.md +0 -54
|
@@ -1,25 +1,72 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
2
3
|
import { cx } from "../_utils/cx.js";
|
|
3
4
|
|
|
4
5
|
/** CyberSkill Menu — dropdown. Provide a `trigger` element; compose MenuItem children. */
|
|
5
|
-
export function Menu({ trigger, children, align = "start", open: controlledOpen, onOpenChange, className }) {
|
|
6
|
+
export function Menu({ trigger, children, align = "start", open: controlledOpen, onOpenChange, lang, className }) {
|
|
6
7
|
const [uOpen, setUOpen] = React.useState(false);
|
|
7
8
|
const open = controlledOpen != null ? controlledOpen : uOpen;
|
|
8
9
|
const set = (v) => { onOpenChange ? onOpenChange(v) : setUOpen(v); };
|
|
9
|
-
const ref =
|
|
10
|
+
const [ref, L] = useLang(lang);
|
|
11
|
+
const t = makeT("Menu", L);
|
|
12
|
+
const triggerRef = React.useRef(null);
|
|
13
|
+
const listRef = React.useRef(null);
|
|
14
|
+
|
|
10
15
|
React.useEffect(() => {
|
|
11
16
|
if (!open) return;
|
|
17
|
+
const items = () => listRef.current
|
|
18
|
+
? [...listRef.current.querySelectorAll('[role="menuitem"]:not([disabled])')]
|
|
19
|
+
: [];
|
|
20
|
+
// FIND-040 — move focus into the menu on open.
|
|
21
|
+
const first = items()[0];
|
|
22
|
+
if (first && first.focus) first.focus();
|
|
23
|
+
|
|
12
24
|
const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) set(false); };
|
|
13
|
-
const onKey = (e) => {
|
|
25
|
+
const onKey = (e) => {
|
|
26
|
+
const opts = items();
|
|
27
|
+
if (e.key === "Escape") {
|
|
28
|
+
e.preventDefault();
|
|
29
|
+
set(false);
|
|
30
|
+
const el = triggerRef.current;
|
|
31
|
+
if (el && el.focus) el.focus();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!opts.length) return;
|
|
35
|
+
const active = document.activeElement;
|
|
36
|
+
const idx = opts.indexOf(active);
|
|
37
|
+
if (e.key === "ArrowDown") {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
(opts[idx < 0 ? 0 : Math.min(opts.length - 1, idx + 1)] || opts[0]).focus();
|
|
40
|
+
} else if (e.key === "ArrowUp") {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
(opts[idx < 0 ? opts.length - 1 : Math.max(0, idx - 1)] || opts[0]).focus();
|
|
43
|
+
} else if (e.key === "Home") {
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
opts[0].focus();
|
|
46
|
+
} else if (e.key === "End") {
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
opts[opts.length - 1].focus();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
14
51
|
document.addEventListener("mousedown", onDoc);
|
|
15
52
|
document.addEventListener("keydown", onKey);
|
|
16
|
-
return () => {
|
|
53
|
+
return () => {
|
|
54
|
+
document.removeEventListener("mousedown", onDoc);
|
|
55
|
+
document.removeEventListener("keydown", onKey);
|
|
56
|
+
};
|
|
17
57
|
}, [open]);
|
|
58
|
+
|
|
18
59
|
const toggle = () => set(!open);
|
|
19
60
|
// ARIA attrs must live on the interactive trigger (button), not a wrapping <span>
|
|
20
61
|
// — axe aria-allowed-attr flags aria-haspopup/aria-expanded on generic elements.
|
|
21
62
|
const triggerNode = React.isValidElement(trigger)
|
|
22
63
|
? React.cloneElement(trigger, {
|
|
64
|
+
ref: (node) => {
|
|
65
|
+
triggerRef.current = node;
|
|
66
|
+
const r = trigger.ref;
|
|
67
|
+
if (typeof r === "function") r(node);
|
|
68
|
+
else if (r && typeof r === "object") r.current = node;
|
|
69
|
+
},
|
|
23
70
|
"aria-haspopup": "menu",
|
|
24
71
|
"aria-expanded": open,
|
|
25
72
|
onClick: (e) => {
|
|
@@ -27,12 +74,19 @@ export function Menu({ trigger, children, align = "start", open: controlledOpen,
|
|
|
27
74
|
if (!e.defaultPrevented) toggle();
|
|
28
75
|
},
|
|
29
76
|
})
|
|
30
|
-
: <button type="button" aria-haspopup="menu" aria-expanded={open} onClick={toggle}>{trigger}</button>;
|
|
77
|
+
: <button type="button" ref={triggerRef} aria-haspopup="menu" aria-expanded={open} onClick={toggle}>{trigger}</button>;
|
|
31
78
|
return (
|
|
32
79
|
<div className={cx("cs-menu", className)} ref={ref}>
|
|
33
80
|
{triggerNode}
|
|
34
81
|
{open ? (
|
|
35
|
-
<div
|
|
82
|
+
<div
|
|
83
|
+
ref={listRef}
|
|
84
|
+
className={cx("cs-menu__list", align === "end" && "cs-menu__list--end")}
|
|
85
|
+
role="menu"
|
|
86
|
+
aria-label={t("menu")}
|
|
87
|
+
>
|
|
88
|
+
{children}
|
|
89
|
+
</div>
|
|
36
90
|
) : null}
|
|
37
91
|
</div>
|
|
38
92
|
);
|
|
@@ -8,6 +8,8 @@ export interface StepItem { title: ReactNode; body?: ReactNode; n?: ReactNode; }
|
|
|
8
8
|
export interface StepsProps {
|
|
9
9
|
steps: StepItem[];
|
|
10
10
|
current?: number;
|
|
11
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
12
|
+
lang?: string;
|
|
11
13
|
className?: string;
|
|
12
14
|
}
|
|
13
15
|
export function Steps(props: StepsProps): React.ReactElement;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
2
3
|
import { cx } from "../_utils/cx.js";
|
|
3
4
|
|
|
4
5
|
/** CyberSkill Steps — horizontal progress stepper. Steps before `current` are done, `current` is active. */
|
|
5
|
-
export function Steps({ steps = [], current = 0, className }) {
|
|
6
|
+
export function Steps({ steps = [], current = 0, lang, className }) {
|
|
7
|
+
const [ref, L] = useLang(lang);
|
|
8
|
+
const t = makeT("Steps", L);
|
|
6
9
|
return (
|
|
7
|
-
<div className={cx("cs-steps", className)}>
|
|
10
|
+
<div ref={ref} className={cx("cs-steps", className)} role="list" aria-label={t("label")}>
|
|
8
11
|
{steps.map((s, i) => {
|
|
9
12
|
const state = i < current ? "done" : i === current ? "active" : "todo";
|
|
10
13
|
return (
|
|
11
|
-
<div key={i} className={cx("cs-step", `cs-step--${state}`)}>
|
|
14
|
+
<div key={i} className={cx("cs-step", `cs-step--${state}`)} role="listitem">
|
|
12
15
|
<span className="cs-step__marker">{state === "done" ? "✓" : s.n || i + 1}</span>
|
|
13
16
|
<span className="cs-step__title">{s.title}</span>
|
|
14
17
|
{s.body ? <span className="cs-step__body">{s.body}</span> : null}
|
|
@@ -11,6 +11,8 @@ export interface TabsProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "o
|
|
|
11
11
|
tabs: TabItem[];
|
|
12
12
|
value?: string;
|
|
13
13
|
onChange?: (value: string) => void;
|
|
14
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
15
|
+
lang?: string;
|
|
14
16
|
}
|
|
15
17
|
export function Tabs(props: TabsProps): React.ReactElement;
|
|
16
18
|
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
2
3
|
import { cx } from "../_utils/cx.js";
|
|
3
4
|
|
|
4
5
|
/** CyberSkill Tabs — data-driven tablist, controlled by value/onChange. Ochre underline on active. */
|
|
5
|
-
export function Tabs({ tabs = [], value, onChange, className, ...props }) {
|
|
6
|
+
export function Tabs({ tabs = [], value, onChange, lang, className, "aria-label": ariaLabel, ...props }) {
|
|
7
|
+
const [ref, L] = useLang(lang);
|
|
8
|
+
const t = makeT("Tabs", L);
|
|
6
9
|
const refs = React.useRef([]);
|
|
7
|
-
const idx = Math.max(0, tabs.findIndex((
|
|
10
|
+
const idx = Math.max(0, tabs.findIndex((tab) => tab.value === value));
|
|
8
11
|
const key = (e, i) => {
|
|
9
12
|
let n = null;
|
|
10
13
|
if (e.key === "ArrowRight") n = (i + 1) % tabs.length;
|
|
@@ -17,7 +20,7 @@ export function Tabs({ tabs = [], value, onChange, className, ...props }) {
|
|
|
17
20
|
const b = refs.current[n]; if (b) b.focus();
|
|
18
21
|
};
|
|
19
22
|
return (
|
|
20
|
-
<div role="tablist" className={cx("cs-tabs", className)} {...props}>
|
|
23
|
+
<div ref={ref} role="tablist" aria-label={ariaLabel ?? t("list")} className={cx("cs-tabs", className)} {...props}>
|
|
21
24
|
{tabs.map((t, i) => (
|
|
22
25
|
<button key={t.value} type="button" role="tab" aria-selected={value === t.value} tabIndex={i === idx ? 0 : -1}
|
|
23
26
|
ref={(el) => (refs.current[i] = el)} onKeyDown={(e) => key(e, i)}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
|
|
3
|
-
/** Horizontal action bar (
|
|
4
|
-
*
|
|
3
|
+
/** Horizontal action bar (APG toolbar: arrow-key roving among controls).
|
|
4
|
+
* Items after `overflowAfter` collapse into a ⋯ menubutton + popup menu
|
|
5
|
+
* (bilingual aria). "-" renders a separator. */
|
|
5
6
|
export type ToolbarItem = { label?: ReactNode; icon?: ReactNode; onSelect?: () => void } | "-";
|
|
6
7
|
export interface ToolbarProps {
|
|
7
8
|
items: ToolbarItem[];
|
|
@@ -2,31 +2,138 @@ import React from "react";
|
|
|
2
2
|
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
3
3
|
import { cx } from "../_utils/cx.js";
|
|
4
4
|
|
|
5
|
-
/** CyberSkill Toolbar — horizontal action bar; overflow items collapse into a
|
|
5
|
+
/** CyberSkill Toolbar — horizontal action bar (APG toolbar arrows); overflow items collapse into a menubutton + popup menu. items: {label,icon,onSelect} or "-". */
|
|
6
6
|
export function Toolbar({ items = [], overflowAfter, label, lang, className }) {
|
|
7
7
|
const [open, setOpen] = React.useState(false);
|
|
8
|
+
const [focusIdx, setFocusIdx] = React.useState(0);
|
|
8
9
|
const wrap = React.useRef(null);
|
|
10
|
+
const btnRefs = React.useRef([]);
|
|
11
|
+
const menuRefs = React.useRef([]);
|
|
9
12
|
const [ref, L] = useLang(lang);
|
|
10
13
|
const t = makeT("Toolbar", L);
|
|
11
14
|
const cut = overflowAfter != null ? overflowAfter : items.length;
|
|
12
|
-
const head = items.slice(0, cut)
|
|
15
|
+
const head = items.slice(0, cut);
|
|
16
|
+
const tail = items.slice(cut).filter((x) => x !== "-");
|
|
17
|
+
const hasMore = tail.length > 0;
|
|
18
|
+
|
|
19
|
+
// Controllable tab stops: head action buttons + optional ⋯ menubutton (separators skipped).
|
|
20
|
+
const controlMeta = [];
|
|
21
|
+
head.forEach((it, i) => {
|
|
22
|
+
if (it !== "-") controlMeta.push({ kind: "head", headIndex: i });
|
|
23
|
+
});
|
|
24
|
+
if (hasMore) controlMeta.push({ kind: "more" });
|
|
25
|
+
|
|
13
26
|
React.useEffect(() => {
|
|
14
27
|
if (!open) return;
|
|
15
28
|
const d = (e) => { if (wrap.current && !wrap.current.contains(e.target)) setOpen(false); };
|
|
16
29
|
document.addEventListener("mousedown", d);
|
|
17
30
|
return () => document.removeEventListener("mousedown", d);
|
|
18
31
|
}, [open]);
|
|
32
|
+
|
|
33
|
+
React.useEffect(() => {
|
|
34
|
+
if (focusIdx >= controlMeta.length) setFocusIdx(Math.max(0, controlMeta.length - 1));
|
|
35
|
+
}, [focusIdx, controlMeta.length]);
|
|
36
|
+
|
|
37
|
+
const focusControl = (i) => {
|
|
38
|
+
const next = Math.max(0, Math.min(controlMeta.length - 1, i));
|
|
39
|
+
setFocusIdx(next);
|
|
40
|
+
requestAnimationFrame(() => {
|
|
41
|
+
const el = btnRefs.current[next];
|
|
42
|
+
if (el) el.focus();
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const onToolbarKeyDown = (e, i) => {
|
|
47
|
+
if (e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
48
|
+
if (e.key === "ArrowRight") { e.preventDefault(); focusControl(i + 1); }
|
|
49
|
+
else if (e.key === "ArrowLeft") { e.preventDefault(); focusControl(i - 1); }
|
|
50
|
+
else if (e.key === "Home") { e.preventDefault(); focusControl(0); }
|
|
51
|
+
else if (e.key === "End") { e.preventDefault(); focusControl(controlMeta.length - 1); }
|
|
52
|
+
else if (e.key === "Escape" && open) { e.preventDefault(); setOpen(false); }
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const onMenuKeyDown = (e, i) => {
|
|
56
|
+
if (e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
57
|
+
if (e.key === "ArrowDown") {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
const n = Math.min(tail.length - 1, i + 1);
|
|
60
|
+
const el = menuRefs.current[n]; if (el) el.focus();
|
|
61
|
+
} else if (e.key === "ArrowUp") {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
const n = Math.max(0, i - 1);
|
|
64
|
+
const el = menuRefs.current[n]; if (el) el.focus();
|
|
65
|
+
} else if (e.key === "Escape") {
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
setOpen(false);
|
|
68
|
+
const moreIdx = controlMeta.findIndex((c) => c.kind === "more");
|
|
69
|
+
if (moreIdx >= 0) focusControl(moreIdx);
|
|
70
|
+
} else if (e.key === "Home") {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
const el = menuRefs.current[0]; if (el) el.focus();
|
|
73
|
+
} else if (e.key === "End") {
|
|
74
|
+
e.preventDefault();
|
|
75
|
+
const el = menuRefs.current[tail.length - 1]; if (el) el.focus();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
let controlI = 0;
|
|
19
80
|
return (
|
|
20
|
-
<div ref={(el) => { wrap.current = el; ref.current = el; }} className={cx("cs-toolbar", className)} role="toolbar" aria-label={label}>
|
|
21
|
-
{head.map((it, i) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
81
|
+
<div ref={(el) => { wrap.current = el; ref.current = el; }} className={cx("cs-toolbar", className)} role="toolbar" aria-label={label} aria-orientation="horizontal">
|
|
82
|
+
{head.map((it, i) => {
|
|
83
|
+
if (it === "-") return <span key={"sep-" + i} className="cs-toolbar__sep" aria-hidden="true" />;
|
|
84
|
+
const ci = controlI++;
|
|
85
|
+
return (
|
|
86
|
+
<button
|
|
87
|
+
key={"btn-" + i}
|
|
88
|
+
type="button"
|
|
89
|
+
className="cs-toolbar__btn"
|
|
90
|
+
tabIndex={ci === focusIdx ? 0 : -1}
|
|
91
|
+
ref={(el) => { btnRefs.current[ci] = el; }}
|
|
92
|
+
onFocus={() => setFocusIdx(ci)}
|
|
93
|
+
onKeyDown={(e) => onToolbarKeyDown(e, ci)}
|
|
94
|
+
onClick={() => it.onSelect && it.onSelect()}
|
|
95
|
+
>{it.icon}{it.label ? <span>{it.label}</span> : null}</button>
|
|
96
|
+
);
|
|
97
|
+
})}
|
|
98
|
+
{hasMore ? (() => {
|
|
99
|
+
const ci = controlI++;
|
|
100
|
+
return (
|
|
101
|
+
<span className="cs-toolbar__more">
|
|
102
|
+
<button
|
|
103
|
+
type="button"
|
|
104
|
+
className="cs-toolbar__btn"
|
|
105
|
+
aria-haspopup="menu"
|
|
106
|
+
aria-expanded={open}
|
|
107
|
+
aria-label={t("more")}
|
|
108
|
+
tabIndex={ci === focusIdx ? 0 : -1}
|
|
109
|
+
ref={(el) => { btnRefs.current[ci] = el; }}
|
|
110
|
+
onFocus={() => setFocusIdx(ci)}
|
|
111
|
+
onKeyDown={(e) => {
|
|
112
|
+
onToolbarKeyDown(e, ci);
|
|
113
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
114
|
+
if (!open) { e.preventDefault(); setOpen(true); requestAnimationFrame(() => { const el = menuRefs.current[0]; if (el) el.focus(); }); }
|
|
115
|
+
}
|
|
116
|
+
}}
|
|
117
|
+
onClick={() => setOpen((o) => !o)}
|
|
118
|
+
>⋯</button>
|
|
119
|
+
{open ? (
|
|
120
|
+
<span className="cs-menu__list" role="menu">
|
|
121
|
+
{tail.map((it, i) => (
|
|
122
|
+
<button
|
|
123
|
+
key={i}
|
|
124
|
+
type="button"
|
|
125
|
+
role="menuitem"
|
|
126
|
+
className="cs-menu__item"
|
|
127
|
+
ref={(el) => { menuRefs.current[i] = el; }}
|
|
128
|
+
onKeyDown={(e) => onMenuKeyDown(e, i)}
|
|
129
|
+
onClick={() => { setOpen(false); it.onSelect && it.onSelect(); }}
|
|
130
|
+
>{it.label}</button>
|
|
131
|
+
))}
|
|
132
|
+
</span>
|
|
133
|
+
) : null}
|
|
134
|
+
</span>
|
|
135
|
+
);
|
|
136
|
+
})() : null}
|
|
30
137
|
</div>
|
|
31
138
|
);
|
|
32
139
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
**Toolbar** — action bar with "⋯" overflow menu and "-" separators.
|
|
1
|
+
**Toolbar** — action bar with APG arrow navigation, "⋯" overflow menubutton + popup menu, and "-" separators. Escape closes the overflow menu.
|
|
2
2
|
|
|
3
3
|
```jsx
|
|
4
4
|
<Toolbar label="Editor" overflowAfter={3} items={[{icon:<Icon name="edit" size="sm"/>,label:"Edit"},"-",{label:"Share"},{label:"Export"},{label:"Archive"}]}/>
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
.lbl { font: 600 11px/1 var(--cs-font-family-ui); text-transform: uppercase; letter-spacing: .09em; color: var(--cs-color-text-muted); margin-bottom: 10px; }
|
|
12
12
|
.row { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
|
|
13
13
|
</style>
|
|
14
|
-
<script src="
|
|
15
|
-
<script src="
|
|
16
|
-
<script src="
|
|
14
|
+
<script src="../../_vendor/react/react.production.min.js"></script>
|
|
15
|
+
<script src="../../_vendor/react/react-dom.production.min.js"></script>
|
|
16
|
+
<script src="../../_vendor/babel/babel.min.js"></script>
|
|
17
17
|
<script src="../../_ds_bundle.js"></script>
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
.frame .cs-cmdk-scrim { position: absolute; padding-top: 14px; }
|
|
14
14
|
.frame .cs-cmdk { inline-size: 100%; box-shadow: none; }
|
|
15
15
|
</style>
|
|
16
|
-
<script src="
|
|
17
|
-
<script src="
|
|
18
|
-
<script src="
|
|
16
|
+
<script src="../../_vendor/react/react.production.min.js"></script>
|
|
17
|
+
<script src="../../_vendor/react/react-dom.production.min.js"></script>
|
|
18
|
+
<script src="../../_vendor/babel/babel.min.js"></script>
|
|
19
19
|
<script src="../../_ds_bundle.js"></script>
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
@@ -1,26 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
3
3
|
import { cx } from "../_utils/cx.js";
|
|
4
|
-
|
|
5
|
-
const FOCUSABLE = [
|
|
6
|
-
'a[href]',
|
|
7
|
-
'area[href]',
|
|
8
|
-
'button:not([disabled])',
|
|
9
|
-
'input:not([disabled]):not([type="hidden"])',
|
|
10
|
-
'select:not([disabled])',
|
|
11
|
-
'textarea:not([disabled])',
|
|
12
|
-
'audio[controls]',
|
|
13
|
-
'video[controls]',
|
|
14
|
-
'summary',
|
|
15
|
-
'iframe',
|
|
16
|
-
'[contenteditable]:not([contenteditable="false"])',
|
|
17
|
-
'[tabindex]:not([tabindex="-1"])',
|
|
18
|
-
].join(",");
|
|
4
|
+
import { useOverlayLayer } from "./OverlayManager.jsx";
|
|
19
5
|
|
|
20
6
|
/**
|
|
21
7
|
* CyberSkill AlertDialog — first-class destructive/confirm modal (role=alertdialog).
|
|
22
8
|
* Distinct from Popconfirm (inline bubble) and Dialog (general modal). Focus trap +
|
|
23
|
-
* restore; bilingual confirm/cancel via the registry.
|
|
9
|
+
* restore via overlay manager; bilingual confirm/cancel via the registry.
|
|
24
10
|
*/
|
|
25
11
|
export function AlertDialog({
|
|
26
12
|
open,
|
|
@@ -53,40 +39,24 @@ export function AlertDialog({
|
|
|
53
39
|
onOpenChange?.(next);
|
|
54
40
|
};
|
|
55
41
|
const destructive = (tone ?? variant) === "destructive";
|
|
56
|
-
const confirmRef = React.useRef(onConfirm);
|
|
57
|
-
|
|
42
|
+
const confirmRef = React.useRef(onConfirm);
|
|
43
|
+
confirmRef.current = onConfirm;
|
|
44
|
+
const cancelRef = React.useRef(onCancel);
|
|
45
|
+
cancelRef.current = onCancel;
|
|
46
|
+
const setOpenRef = React.useRef(setOpen);
|
|
47
|
+
setOpenRef.current = setOpen;
|
|
58
48
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
setOpen(false);
|
|
71
|
-
cancelRef.current?.();
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (e.key !== "Tab" || !panel.current) return;
|
|
75
|
-
const f = focusables();
|
|
76
|
-
if (!f.length) { e.preventDefault(); panel.current.focus(); return; }
|
|
77
|
-
const a = f[0], z = f[f.length - 1];
|
|
78
|
-
const active = document.activeElement;
|
|
79
|
-
const inside = panel.current.contains(active);
|
|
80
|
-
if (e.shiftKey && (!inside || active === a)) { e.preventDefault(); z.focus(); }
|
|
81
|
-
else if (!e.shiftKey && (!inside || active === z)) { e.preventDefault(); a.focus(); }
|
|
82
|
-
};
|
|
83
|
-
document.addEventListener("keydown", k);
|
|
84
|
-
return () => {
|
|
85
|
-
document.removeEventListener("keydown", k);
|
|
86
|
-
document.body.style.overflow = prevOverflow;
|
|
87
|
-
if (prev && prev.focus) prev.focus();
|
|
88
|
-
};
|
|
89
|
-
}, [isOpen]);
|
|
49
|
+
useOverlayLayer({
|
|
50
|
+
open: isOpen,
|
|
51
|
+
kind: "modal",
|
|
52
|
+
trapFocus: true,
|
|
53
|
+
preferFocusSelector: ".cs-alert-dialog__confirm",
|
|
54
|
+
onEscape: () => {
|
|
55
|
+
setOpenRef.current(false);
|
|
56
|
+
cancelRef.current?.();
|
|
57
|
+
},
|
|
58
|
+
panelRef: panel,
|
|
59
|
+
});
|
|
90
60
|
|
|
91
61
|
const cl = cancelLabel != null ? cancelLabel : t("cancel");
|
|
92
62
|
const cf = confirmLabel != null ? confirmLabel : t("confirm");
|
|
@@ -5,6 +5,8 @@ export type ContextMenuItem = { label: ReactNode; onSelect?: () => void; danger?
|
|
|
5
5
|
export interface ContextMenuProps {
|
|
6
6
|
items: ContextMenuItem[];
|
|
7
7
|
children?: ReactNode;
|
|
8
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
9
|
+
lang?: string;
|
|
8
10
|
className?: string;
|
|
9
11
|
}
|
|
10
12
|
export function ContextMenu(props: ContextMenuProps): React.ReactElement;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
2
3
|
import { cx } from "../_utils/cx.js";
|
|
3
4
|
|
|
4
5
|
/** CyberSkill ContextMenu — right-click menu scoped to its children. items: {label,onSelect,danger} or "-" separator. */
|
|
5
|
-
export function ContextMenu({ items = [], children, className }) {
|
|
6
|
+
export function ContextMenu({ items = [], children, lang, className }) {
|
|
6
7
|
const [pos, setPos] = React.useState(null);
|
|
8
|
+
const [ref, L] = useLang(lang);
|
|
9
|
+
const t = makeT("ContextMenu", L);
|
|
7
10
|
React.useEffect(() => {
|
|
8
11
|
if (!pos) return;
|
|
9
12
|
const close = () => setPos(null);
|
|
@@ -13,11 +16,11 @@ export function ContextMenu({ items = [], children, className }) {
|
|
|
13
16
|
return () => { document.removeEventListener("click", close); document.removeEventListener("keydown", k); };
|
|
14
17
|
}, [pos]);
|
|
15
18
|
return (
|
|
16
|
-
<div className={cx("cs-ctxmenu-zone", className)}
|
|
19
|
+
<div ref={ref} className={cx("cs-ctxmenu-zone", className)}
|
|
17
20
|
onContextMenu={(e) => { e.preventDefault(); const r = e.currentTarget.getBoundingClientRect(); setPos({ x: e.clientX - r.left, y: e.clientY - r.top }); }}>
|
|
18
21
|
{children}
|
|
19
22
|
{pos ? (
|
|
20
|
-
<div className="cs-menu__list" role="menu" style={{ position: "absolute", insetInlineStart: pos.x, insetBlockStart: pos.y }}>
|
|
23
|
+
<div className="cs-menu__list" role="menu" aria-label={t("menu")} style={{ position: "absolute", insetInlineStart: pos.x, insetBlockStart: pos.y }}>
|
|
21
24
|
{items.map((it, i) => it === "-"
|
|
22
25
|
? <div key={i} className="cs-menu__sep" />
|
|
23
26
|
: <button key={i} type="button" role="menuitem" className={cx("cs-menu__item", it.danger && "cs-menu__item--danger")} onClick={() => { setPos(null); it.onSelect && it.onSelect(); }}>{it.label}</button>)}
|
|
@@ -13,6 +13,8 @@ export interface DrawerProps {
|
|
|
13
13
|
side?: "right" | "left";
|
|
14
14
|
children?: ReactNode;
|
|
15
15
|
actions?: ReactNode;
|
|
16
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
17
|
+
lang?: string;
|
|
16
18
|
className?: string;
|
|
17
19
|
}
|
|
18
20
|
export function Drawer(props: DrawerProps): React.ReactElement | null;
|
|
@@ -1,35 +1,39 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
3
3
|
import { cx } from "../_utils/cx.js";
|
|
4
|
+
import { useOverlayLayer } from "./OverlayManager.jsx";
|
|
4
5
|
|
|
5
6
|
/** CyberSkill Drawer — slide-in side panel with scrim. side: right (default) | left. */
|
|
6
7
|
export function Drawer({ open, onClose, title, side = "right", children, actions, lang, className }) {
|
|
7
8
|
const [ref, L] = useLang(lang);
|
|
8
|
-
React.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const a = f[0], z = f[f.length - 1];
|
|
21
|
-
if (e.shiftKey && document.activeElement === a) { e.preventDefault(); z.focus(); }
|
|
22
|
-
else if (!e.shiftKey && document.activeElement === z) { e.preventDefault(); a.focus(); }
|
|
23
|
-
};
|
|
24
|
-
document.addEventListener("keydown", k);
|
|
25
|
-
return () => { document.removeEventListener("keydown", k); if (prev && prev.focus) prev.focus(); };
|
|
26
|
-
}, [open]);
|
|
9
|
+
const panel = React.useRef(null);
|
|
10
|
+
const closeRef = React.useRef(onClose);
|
|
11
|
+
closeRef.current = onClose;
|
|
12
|
+
|
|
13
|
+
useOverlayLayer({
|
|
14
|
+
open: !!open,
|
|
15
|
+
kind: "modal",
|
|
16
|
+
trapFocus: true,
|
|
17
|
+
onEscape: () => closeRef.current && closeRef.current(),
|
|
18
|
+
panelRef: panel,
|
|
19
|
+
});
|
|
20
|
+
|
|
27
21
|
const t = makeT("Drawer", L);
|
|
28
22
|
if (!open) return null;
|
|
29
23
|
return (
|
|
30
24
|
<>
|
|
31
25
|
<div className="cs-drawer-scrim" onClick={onClose} aria-hidden="true" />
|
|
32
|
-
<aside
|
|
26
|
+
<aside
|
|
27
|
+
ref={(el) => {
|
|
28
|
+
panel.current = el;
|
|
29
|
+
ref.current = el;
|
|
30
|
+
}}
|
|
31
|
+
tabIndex={-1}
|
|
32
|
+
className={cx("cs-drawer", side === "left" && "cs-drawer--left", className)}
|
|
33
|
+
role="dialog"
|
|
34
|
+
aria-modal="true"
|
|
35
|
+
aria-label={typeof title === "string" ? title : t("panel")}
|
|
36
|
+
>
|
|
33
37
|
<div className="cs-drawer__header">
|
|
34
38
|
{title ? <h2 className="cs-drawer__title">{title}</h2> : null}
|
|
35
39
|
<button type="button" className="cs-drawer__close" aria-label={t("close")} onClick={onClose}>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ReactNode, RefObject } from "react";
|
|
2
|
+
|
|
3
|
+
export type OverlayLayerKind = "dropdown" | "popover" | "modal" | "toast" | "tour";
|
|
4
|
+
|
|
5
|
+
export type OverlayLayerRegistration = {
|
|
6
|
+
id?: string;
|
|
7
|
+
kind: OverlayLayerKind;
|
|
8
|
+
trapFocus?: boolean;
|
|
9
|
+
lockScroll?: boolean;
|
|
10
|
+
onEscape?: () => void;
|
|
11
|
+
restoreEl?: HTMLElement | null;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type OverlayManagerApi = {
|
|
15
|
+
register(layer: OverlayLayerRegistration): () => void;
|
|
16
|
+
top(): OverlayLayerRegistration | null;
|
|
17
|
+
readonly scrollLocked: boolean;
|
|
18
|
+
readonly depth: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function getOverlayManager(): OverlayManagerApi;
|
|
22
|
+
|
|
23
|
+
export function OverlayProvider(props: { children?: ReactNode }): JSX.Element;
|
|
24
|
+
|
|
25
|
+
export function useOverlayLayer(opts: {
|
|
26
|
+
open: boolean;
|
|
27
|
+
kind?: OverlayLayerKind;
|
|
28
|
+
trapFocus?: boolean;
|
|
29
|
+
lockScroll?: boolean;
|
|
30
|
+
onEscape?: () => void;
|
|
31
|
+
panelRef?: RefObject<HTMLElement | null>;
|
|
32
|
+
preferFocusSelector?: string;
|
|
33
|
+
}): { manager: OverlayManagerApi };
|
|
34
|
+
|
|
35
|
+
export function attachFocusTrap(
|
|
36
|
+
panelEl: HTMLElement | null,
|
|
37
|
+
opts?: { handleEscape?: boolean; onEscape?: () => void }
|
|
38
|
+
): () => void;
|
|
39
|
+
|
|
40
|
+
export const focusableSelector: string;
|