@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
|
@@ -9,6 +9,8 @@ export interface FileUploadProps {
|
|
|
9
9
|
multiple?: boolean;
|
|
10
10
|
onFiles?: (files: File[]) => void;
|
|
11
11
|
icon?: ReactNode;
|
|
12
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
13
|
+
lang?: string;
|
|
12
14
|
className?: string;
|
|
13
15
|
}
|
|
14
16
|
export function FileUpload(props: FileUploadProps): React.ReactElement;
|
|
@@ -2,28 +2,42 @@ 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 FileUpload — click-or-drag dropzone. Calls onFiles(File[]) on select/drop.
|
|
5
|
+
/** CyberSkill FileUpload — click-or-drag dropzone. Calls onFiles(File[]) on select/drop.
|
|
6
|
+
* Uses a single labeled <input type="file"> (no nested interactive) for axe name/role. */
|
|
6
7
|
export function FileUpload({ title, hint, accept, multiple = false, onFiles, icon, lang, className }) {
|
|
7
8
|
const [drag, setDrag] = React.useState(false);
|
|
9
|
+
const inputRef = React.useRef(null);
|
|
8
10
|
const pick = (files) => { if (files && files.length && onFiles) onFiles(Array.from(files)); };
|
|
9
11
|
const [ref, L] = useLang(lang);
|
|
10
12
|
const t = makeT("FileUpload", L);
|
|
11
13
|
const tt = title != null ? title : t("title");
|
|
12
14
|
const hh = hint != null ? hint : t("hint");
|
|
15
|
+
const id = React.useId();
|
|
13
16
|
return (
|
|
14
|
-
<
|
|
17
|
+
<div
|
|
15
18
|
ref={ref}
|
|
16
19
|
className={cx("cs-dropzone", drag && "is-dragging", className)}
|
|
17
20
|
onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
|
|
18
21
|
onDragLeave={() => setDrag(false)}
|
|
19
22
|
onDrop={(e) => { e.preventDefault(); setDrag(false); pick(e.dataTransfer.files); }}
|
|
23
|
+
onClick={() => inputRef.current && inputRef.current.click()}
|
|
20
24
|
>
|
|
21
|
-
<span className="cs-dropzone__icon">
|
|
22
|
-
{icon ?? <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"
|
|
25
|
+
<span className="cs-dropzone__icon" aria-hidden="true">
|
|
26
|
+
{icon ?? <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M12 16V4M7 9l5-5 5 5" /><path d="M5 16v3a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-3" /></svg>}
|
|
23
27
|
</span>
|
|
24
|
-
<
|
|
25
|
-
<span className="cs-dropzone__hint">{hh}</span>
|
|
26
|
-
<input
|
|
27
|
-
|
|
28
|
+
<label className="cs-dropzone__title" htmlFor={id}>{tt}</label>
|
|
29
|
+
<span className="cs-dropzone__hint" id={id + "-hint"}>{hh}</span>
|
|
30
|
+
<input
|
|
31
|
+
id={id}
|
|
32
|
+
ref={inputRef}
|
|
33
|
+
type="file"
|
|
34
|
+
accept={accept}
|
|
35
|
+
multiple={multiple}
|
|
36
|
+
className="cs-sr-only"
|
|
37
|
+
aria-describedby={id + "-hint"}
|
|
38
|
+
onChange={(e) => pick(e.target.files)}
|
|
39
|
+
onClick={(e) => e.stopPropagation()}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
28
42
|
);
|
|
29
43
|
}
|
|
@@ -13,7 +13,9 @@ export interface FormProps {
|
|
|
13
13
|
errors?: Record<string, string | undefined>;
|
|
14
14
|
/** name → rule or rule[]; validated on submit. */
|
|
15
15
|
rules?: Record<string, FormRule | FormRule[]>;
|
|
16
|
-
/** name → async (value, values) => message | null; runs after sync rules pass.
|
|
16
|
+
/** name → async (value, values) => message | null; runs after sync rules pass.
|
|
17
|
+
* While awaiting, Form sets `is-pending` / `aria-busy`, disables controls via CSS,
|
|
18
|
+
* and ignores duplicate submits. Context exposes `pending: boolean`. */
|
|
17
19
|
asyncRules?: Record<string, (value: unknown, values: Record<string, unknown>) => Promise<string | null | undefined>>;
|
|
18
20
|
/** Seed for controller-registered fields. */
|
|
19
21
|
initialValues?: Record<string, unknown>;
|
|
@@ -55,6 +55,7 @@ export function Form({ onSubmit, errors = {}, rules, asyncRules, initialValues,
|
|
|
55
55
|
const [values, setValues] = React.useState(() => initialValues || {});
|
|
56
56
|
const [ruleErrors, setRuleErrors] = React.useState({});
|
|
57
57
|
const [pending, setPending] = React.useState(false);
|
|
58
|
+
const pendingRef = React.useRef(false);
|
|
58
59
|
const setValue = React.useCallback((name, v) => {
|
|
59
60
|
setValues((s) => (String(name).includes(".") ? setPath(s, name, v) : { ...s, [name]: v }));
|
|
60
61
|
setRuleErrors((e) => (e[name] ? { ...e, [name]: undefined } : e));
|
|
@@ -96,20 +97,27 @@ export function Form({ onSubmit, errors = {}, rules, asyncRules, initialValues,
|
|
|
96
97
|
return (
|
|
97
98
|
<Ctx.Provider value={ctx}>
|
|
98
99
|
<form {...props} ref={ref} className={cx("cs-form", pending && "is-pending", className)} noValidate
|
|
100
|
+
aria-busy={pending || undefined}
|
|
99
101
|
onSubmit={async (e) => {
|
|
100
102
|
e.preventDefault();
|
|
103
|
+
// FIND-015 / FIND-044 — lock re-entry while async validation / submit runs.
|
|
104
|
+
if (pendingRef.current) return;
|
|
101
105
|
const fd = new FormData(e.currentTarget);
|
|
102
106
|
const v = {}; fd.forEach((val, k) => { v[k] = val; });
|
|
103
107
|
Object.assign(v, values); // controller-registered fields are the source of truth
|
|
104
108
|
const errs = runRules(v);
|
|
105
109
|
if (Object.keys(errs).some((k) => errs[k])) { setRuleErrors(errs); return; }
|
|
110
|
+
pendingRef.current = true;
|
|
106
111
|
setPending(true);
|
|
107
112
|
try {
|
|
108
113
|
const aerrs = await runAsyncRules(v);
|
|
109
114
|
setRuleErrors(aerrs);
|
|
110
115
|
if (Object.keys(aerrs).some((k) => aerrs[k])) return;
|
|
111
116
|
onSubmit && onSubmit(v);
|
|
112
|
-
} finally {
|
|
117
|
+
} finally {
|
|
118
|
+
pendingRef.current = false;
|
|
119
|
+
setPending(false);
|
|
120
|
+
}
|
|
113
121
|
}}>
|
|
114
122
|
{keys.length ? (
|
|
115
123
|
<div className="cs-form__summary" role="alert">
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
Manual mode unchanged: omit `rules`/`name`, pass `errors={{email:"…"}}` yourself.
|
|
12
12
|
|
|
13
|
-
**asyncRules:** optional map of field name → async `(value, values) => message|null`. Runs after sync `rules` pass;
|
|
13
|
+
**asyncRules:** optional map of field name → async `(value, values) => message|null`. Runs after sync `rules` pass; Form emits `is-pending` + `aria-busy`, locks controls, and refuses re-entry until the async pass finishes (FIND-015 / FIND-044). Controllers can also read `pending` from Form context.
|
|
14
14
|
|
|
15
15
|
**FormFieldArray** — manage an array of row objects under `name` on the surrounding Form. Children render-prop: `({ index, item, remove, path })`.
|
|
16
16
|
|
|
@@ -2,28 +2,80 @@ import React from "react";
|
|
|
2
2
|
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
3
3
|
import { cx } from "../_utils/cx.js";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
let mentionsUid = 0;
|
|
6
|
+
|
|
7
|
+
/** CyberSkill Mentions — textarea that suggests @users while typing (APG editable combobox). */
|
|
6
8
|
export function Mentions({ value, defaultValue = "", onChange, users = [], placeholder, rows = 3, lang, className }) {
|
|
7
9
|
const [inner, setInner] = React.useState(defaultValue);
|
|
8
10
|
const val = value != null ? value : inner;
|
|
9
11
|
const set = (v) => { if (value == null) setInner(v); onChange && onChange(v); };
|
|
10
12
|
const [q, setQ] = React.useState(null);
|
|
13
|
+
const [activeIndex, setActiveIndex] = React.useState(0);
|
|
14
|
+
const [listId] = React.useState(() => "cs-mentions-" + (++mentionsUid));
|
|
11
15
|
const [ref, L] = useLang(lang);
|
|
12
16
|
const t = makeT("Mentions", L);
|
|
13
17
|
const ph = placeholder != null ? placeholder : t("placeholder");
|
|
18
|
+
const hits = q == null ? [] : users.filter((u) => u.toLowerCase().includes(q)).slice(0, 6);
|
|
19
|
+
const open = hits.length > 0;
|
|
20
|
+
|
|
21
|
+
React.useEffect(() => {
|
|
22
|
+
setActiveIndex((i) => (hits.length ? Math.min(i, hits.length - 1) : 0));
|
|
23
|
+
}, [q, users]);
|
|
24
|
+
|
|
14
25
|
const onInput = (v) => {
|
|
15
26
|
set(v);
|
|
16
27
|
const m = /(^|\s)@(\w*)$/.exec(v);
|
|
17
|
-
|
|
28
|
+
const next = m ? m[2].toLowerCase() : null;
|
|
29
|
+
setQ(next);
|
|
30
|
+
if (next != null) setActiveIndex(0);
|
|
18
31
|
};
|
|
19
|
-
const hits = q == null ? [] : users.filter((u) => u.toLowerCase().includes(q)).slice(0, 6);
|
|
20
32
|
const pick = (u) => { set(val.replace(/(^|\s)@\w*$/, "$1@" + u + " ")); setQ(null); };
|
|
33
|
+
const optionId = (i) => listId + "-opt-" + i;
|
|
34
|
+
const onKeyDown = (e) => {
|
|
35
|
+
if (e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
36
|
+
if (!open) return;
|
|
37
|
+
if (e.key === "ArrowDown") {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
setActiveIndex((i) => Math.min(hits.length - 1, i + 1));
|
|
40
|
+
} else if (e.key === "ArrowUp") {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
setActiveIndex((i) => Math.max(0, i - 1));
|
|
43
|
+
} else if (e.key === "Enter") {
|
|
44
|
+
if (hits[activeIndex]) { e.preventDefault(); pick(hits[activeIndex]); }
|
|
45
|
+
} else if (e.key === "Escape") {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
setQ(null);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
21
50
|
return (
|
|
22
51
|
<span ref={ref} className={cx("cs-mentions", className)}>
|
|
23
|
-
<textarea
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
52
|
+
<textarea
|
|
53
|
+
className="cs-field__control"
|
|
54
|
+
rows={rows}
|
|
55
|
+
value={val}
|
|
56
|
+
placeholder={ph}
|
|
57
|
+
role="combobox"
|
|
58
|
+
aria-autocomplete="list"
|
|
59
|
+
aria-expanded={open}
|
|
60
|
+
aria-controls={listId}
|
|
61
|
+
aria-activedescendant={open && hits[activeIndex] ? optionId(activeIndex) : undefined}
|
|
62
|
+
onChange={(e) => onInput(e.target.value)}
|
|
63
|
+
onKeyDown={onKeyDown}
|
|
64
|
+
/>
|
|
65
|
+
{open ? (
|
|
66
|
+
<span className="cs-mentions__pop" role="listbox" id={listId}>
|
|
67
|
+
{hits.map((u, i) => (
|
|
68
|
+
<button
|
|
69
|
+
key={u}
|
|
70
|
+
type="button"
|
|
71
|
+
id={optionId(i)}
|
|
72
|
+
role="option"
|
|
73
|
+
aria-selected={i === activeIndex}
|
|
74
|
+
className={cx(i === activeIndex && "hl")}
|
|
75
|
+
onMouseEnter={() => setActiveIndex(i)}
|
|
76
|
+
onMouseDown={(e) => { e.preventDefault(); pick(u); }}
|
|
77
|
+
>@{u}</button>
|
|
78
|
+
))}
|
|
27
79
|
</span>
|
|
28
80
|
) : null}
|
|
29
81
|
</span>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
**Mentions** — textarea suggesting @users as you type.
|
|
1
|
+
**Mentions** — textarea suggesting @users as you type (APG editable combobox).
|
|
2
|
+
|
|
3
|
+
Keyboard: ArrowUp/Down move the active suggestion (`aria-activedescendant`); Enter selects; Escape closes. Mouse click still picks.
|
|
2
4
|
|
|
3
5
|
```jsx
|
|
4
6
|
<Mentions users={["anle","baovu","lumi"]} placeholder="Add a note — @ to mention"/>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
/** Whole-star rating (radiogroup). Controlled
|
|
2
|
-
* (defaultValue). Clicking the current value
|
|
1
|
+
/** Whole-star rating (APG radiogroup: roving tabindex + arrow keys). Controlled
|
|
2
|
+
* (value/onChange) or uncontrolled (defaultValue). Clicking the current value
|
|
3
|
+
* clears to 0. readOnly for display. */
|
|
3
4
|
export interface RatingProps {
|
|
4
5
|
value?: number;
|
|
5
6
|
defaultValue?: number;
|
|
@@ -3,17 +3,48 @@ import { makeT, useLang } from "../_i18n/i18n.js";
|
|
|
3
3
|
import { cx } from "../_utils/cx.js";
|
|
4
4
|
const STAR = "M12 2l2.9 6.2 6.6.8-4.9 4.6 1.3 6.5L12 16.9 6.1 20l1.3-6.5L2.5 9l6.6-.8z";
|
|
5
5
|
|
|
6
|
-
/** CyberSkill Rating — whole-star rating. Controlled or uncontrolled; readOnly for display. Click the current value to clear. */
|
|
6
|
+
/** CyberSkill Rating — whole-star rating (APG radiogroup: roving tabindex + arrows). Controlled or uncontrolled; readOnly for display. Click the current value to clear. */
|
|
7
7
|
export function Rating({ value, defaultValue = 0, onChange, max = 5, readOnly = false, label, lang, className }) {
|
|
8
8
|
const [inner, setInner] = React.useState(defaultValue);
|
|
9
9
|
const val = value != null ? value : inner;
|
|
10
|
-
const
|
|
10
|
+
const commit = (n) => { if (readOnly) return; if (value == null) setInner(n); onChange && onChange(n); };
|
|
11
|
+
const set = (n) => commit(n === val ? 0 : n);
|
|
11
12
|
const [ref, L] = useLang(lang);
|
|
12
13
|
const lbl = label != null ? label : makeT("Rating", L)("label");
|
|
14
|
+
const refs = React.useRef([]);
|
|
15
|
+
const focusIdx = val > 0 ? Math.min(max, val) - 1 : 0;
|
|
16
|
+
|
|
17
|
+
const move = (from, delta) => {
|
|
18
|
+
if (readOnly) return;
|
|
19
|
+
const next = Math.max(0, Math.min(max - 1, from + delta));
|
|
20
|
+
commit(next + 1);
|
|
21
|
+
const b = refs.current[next];
|
|
22
|
+
if (b) b.focus();
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const onKeyDown = (e, i) => {
|
|
26
|
+
if (readOnly || e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
27
|
+
if (e.key === "ArrowRight" || e.key === "ArrowUp") { e.preventDefault(); move(i, 1); }
|
|
28
|
+
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") { e.preventDefault(); move(i, -1); }
|
|
29
|
+
else if (e.key === "Home") { e.preventDefault(); move(i, -i); }
|
|
30
|
+
else if (e.key === "End") { e.preventDefault(); move(i, max - 1 - i); }
|
|
31
|
+
};
|
|
32
|
+
|
|
13
33
|
return (
|
|
14
34
|
<div ref={ref} className={cx("cs-rating", className)} role="radiogroup" aria-label={lbl + ": " + val + " / " + max} data-readonly={readOnly ? "true" : undefined}>
|
|
15
35
|
{Array.from({ length: max }).map((_, i) => (
|
|
16
|
-
<button
|
|
36
|
+
<button
|
|
37
|
+
key={i}
|
|
38
|
+
type="button"
|
|
39
|
+
role="radio"
|
|
40
|
+
aria-checked={i < val}
|
|
41
|
+
aria-label={(i + 1) + " / " + max}
|
|
42
|
+
className={i < val ? "on" : undefined}
|
|
43
|
+
onClick={() => set(i + 1)}
|
|
44
|
+
tabIndex={readOnly ? -1 : (i === focusIdx ? 0 : -1)}
|
|
45
|
+
ref={(el) => { refs.current[i] = el; }}
|
|
46
|
+
onKeyDown={(e) => onKeyDown(e, i)}
|
|
47
|
+
>
|
|
17
48
|
<svg width="22" height="22" viewBox="0 0 24 24" fill={i < val ? "currentColor" : "none"} stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round" aria-hidden="true"><path d={STAR} /></svg>
|
|
18
49
|
</button>
|
|
19
50
|
))}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
**Rating** — whole-star rating (ochre stars). Controlled or uncontrolled; `readOnly` for display; click current value to clear. Bilingual aria via the registry.
|
|
1
|
+
**Rating** — whole-star rating (ochre stars). APG radiogroup: one tab stop, ArrowLeft/Right (and Up/Down) change value. Controlled or uncontrolled; `readOnly` for display; click current value to clear. Bilingual aria via the registry.
|
|
2
2
|
|
|
3
3
|
```jsx
|
|
4
4
|
<Rating defaultValue={4} onChange={setStars}/>
|
|
@@ -14,6 +14,8 @@ export interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElemen
|
|
|
14
14
|
/** Options as data; alternatively pass <option> children. */
|
|
15
15
|
options?: SelectOption[];
|
|
16
16
|
children?: ReactNode;
|
|
17
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
18
|
+
lang?: string;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export function Select(props: SelectProps): React.ReactElement;
|
|
@@ -1,20 +1,24 @@
|
|
|
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 Select — native <select> in the .cs-field frame with a chevron.
|
|
5
6
|
* Pass `options` [{value,label}] or <option> children. */
|
|
6
|
-
export function Select({ id, label, description, error, options, children, disabled = false, className, ...props }) {
|
|
7
|
+
export function Select({ id, label, description, error, options, children, disabled = false, lang, className, placeholder, ...props }) {
|
|
8
|
+
const [ref, L] = useLang(lang);
|
|
9
|
+
const t = makeT("Select", L);
|
|
7
10
|
const gid = React.useId();
|
|
8
11
|
const sid = id ?? gid;
|
|
9
12
|
const descId = description ? sid + "-desc" : undefined;
|
|
10
13
|
const errId = error ? sid + "-err" : undefined;
|
|
11
14
|
const describedBy = [descId, errId].filter(Boolean).join(" ") || undefined;
|
|
12
15
|
return (
|
|
13
|
-
<label className={cx("cs-field", disabled && "is-disabled", error && "is-invalid", className)} htmlFor={sid}>
|
|
16
|
+
<label ref={ref} className={cx("cs-field", disabled && "is-disabled", error && "is-invalid", className)} htmlFor={sid}>
|
|
14
17
|
{label ? <span className="cs-field__label">{label}</span> : null}
|
|
15
18
|
{description ? <span id={descId} className="cs-field__description">{description}</span> : null}
|
|
16
19
|
<span className="cs-select">
|
|
17
20
|
<select {...props} id={sid} disabled={disabled} aria-invalid={error ? true : undefined} aria-describedby={describedBy} className="cs-field__control">
|
|
21
|
+
{placeholder != null || !children ? <option value="" disabled hidden>{placeholder ?? t("placeholder")}</option> : null}
|
|
18
22
|
{options ? options.map((o) => <option key={o.value} value={o.value}>{o.label}</option>) : children}
|
|
19
23
|
</select>
|
|
20
24
|
<span className="cs-select__chevron" aria-hidden="true">
|
|
@@ -4,3 +4,5 @@ import type * as React from "react";
|
|
|
4
4
|
* range props (min, max, step, value, defaultValue, onChange). */
|
|
5
5
|
export interface SliderProps extends React.InputHTMLAttributes<HTMLInputElement> {}
|
|
6
6
|
export function Slider(props: SliderProps): React.ReactElement;
|
|
7
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
8
|
+
lang?: string;
|
|
@@ -1,8 +1,11 @@
|
|
|
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 Slider — brand-tinted native range input. Pass native props (min/max/step/value/onChange). */
|
|
5
6
|
// `children` is destructured but never rendered on purpose: keeps stray children out of {...props} → void <input>.
|
|
6
|
-
export function Slider({ className, children, ...props }) {
|
|
7
|
-
|
|
7
|
+
export function Slider({ className, children, lang, "aria-label": ariaLabel, ...props }) {
|
|
8
|
+
const [ref, L] = useLang(lang);
|
|
9
|
+
const t = makeT("Slider", L);
|
|
10
|
+
return <input ref={ref} type="range" className={cx("cs-slider", className)} aria-label={ariaLabel ?? t("label")} {...props} />;
|
|
8
11
|
}
|
|
@@ -7,6 +7,8 @@ import type { ReactNode } from "react";
|
|
|
7
7
|
*/
|
|
8
8
|
export interface SwitchProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
|
|
9
9
|
label?: ReactNode;
|
|
10
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
11
|
+
lang?: string;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export function Switch(props: SwitchProps): React.ReactElement;
|
|
@@ -1,12 +1,24 @@
|
|
|
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 Switch — accessible toggle (role="switch"); Umber on, Ochre knob-track in dark. */
|
|
5
6
|
// `children` is destructured but never rendered on purpose: keeps stray children out of {...props} → void <input>.
|
|
6
|
-
export function Switch({ label, disabled = false, className, children, ...props }) {
|
|
7
|
+
export function Switch({ label, disabled = false, className, children, lang, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...props }) {
|
|
8
|
+
const [ref, L] = useLang(lang);
|
|
9
|
+
const t = makeT("Switch", L);
|
|
10
|
+
const named = !!(label || ariaLabel || ariaLabelledby);
|
|
11
|
+
const fallback = props.checked || props.defaultChecked ? t("on") : t("off");
|
|
7
12
|
return (
|
|
8
|
-
<label className={cx("cs-switch", disabled && "is-disabled", className)}>
|
|
9
|
-
<input
|
|
13
|
+
<label ref={ref} className={cx("cs-switch", disabled && "is-disabled", className)}>
|
|
14
|
+
<input
|
|
15
|
+
type="checkbox"
|
|
16
|
+
role="switch"
|
|
17
|
+
disabled={disabled}
|
|
18
|
+
aria-label={ariaLabel ?? (named ? undefined : fallback)}
|
|
19
|
+
aria-labelledby={ariaLabelledby}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
10
22
|
<span className="cs-switch__track" aria-hidden="true" />
|
|
11
23
|
{label ? <span className="cs-switch__label">{label}</span> : null}
|
|
12
24
|
</label>
|
|
@@ -7,8 +7,10 @@ const CLOCK = <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke
|
|
|
7
7
|
export function TimePicker({ value = "09:00", onChange, step = 30, label, disabled = false, lang, className }) {
|
|
8
8
|
const [ref, L] = useLang(lang);
|
|
9
9
|
const t = makeT("TimePicker", L);
|
|
10
|
+
const stepMin = Number(step);
|
|
11
|
+
const safeStep = Number.isFinite(stepMin) && stepMin > 0 ? stepMin : 30;
|
|
10
12
|
const opts = [];
|
|
11
|
-
for (let m = 0; m < 24 * 60; m +=
|
|
13
|
+
for (let m = 0; m < 24 * 60; m += safeStep) {
|
|
12
14
|
opts.push(String(Math.floor(m / 60)).padStart(2, "0") + ":" + String(m % 60).padStart(2, "0"));
|
|
13
15
|
}
|
|
14
16
|
return (
|
|
@@ -11,6 +11,8 @@ export interface ToggleProps {
|
|
|
11
11
|
icon?: ReactNode;
|
|
12
12
|
children?: ReactNode;
|
|
13
13
|
disabled?: boolean;
|
|
14
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
15
|
+
lang?: string;
|
|
14
16
|
className?: string;
|
|
15
17
|
}
|
|
16
18
|
export function Toggle(props: ToggleProps): React.ReactElement;
|
|
@@ -1,13 +1,25 @@
|
|
|
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 Toggle — a single pressable on/off button (≠ Switch: no form semantics; ≠ SegmentedControl: standalone). */
|
|
5
|
-
export function Toggle({ pressed, defaultPressed = false, onChange, icon, children, disabled = false, className, ...props }) {
|
|
6
|
+
export function Toggle({ pressed, defaultPressed = false, onChange, icon, children, disabled = false, lang, className, "aria-label": ariaLabel, ...props }) {
|
|
6
7
|
const [inner, setInner] = React.useState(defaultPressed);
|
|
7
8
|
const on = pressed != null ? pressed : inner;
|
|
9
|
+
const [ref, L] = useLang(lang);
|
|
10
|
+
const t = makeT("Toggle", L);
|
|
8
11
|
const flip = () => { const v = !on; if (pressed == null) setInner(v); onChange && onChange(v); };
|
|
9
12
|
return (
|
|
10
|
-
<button
|
|
13
|
+
<button
|
|
14
|
+
ref={ref}
|
|
15
|
+
type="button"
|
|
16
|
+
className={cx("cs-toggle", className)}
|
|
17
|
+
aria-pressed={on}
|
|
18
|
+
aria-label={ariaLabel ?? (on ? t("pressed") : t("unpressed"))}
|
|
19
|
+
disabled={disabled}
|
|
20
|
+
onClick={flip}
|
|
21
|
+
{...props}
|
|
22
|
+
>
|
|
11
23
|
{icon ? <span aria-hidden="true" style={{ display: "inline-flex" }}>{icon}</span> : null}
|
|
12
24
|
{children}
|
|
13
25
|
</button>
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
.row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
|
|
11
11
|
.lbl { width: 100%; font: 600 11px/1 var(--cs-font-family-ui); text-transform: uppercase; letter-spacing: .09em; color: var(--cs-color-text-muted); }
|
|
12
12
|
</style>
|
|
13
|
-
<script src="
|
|
14
|
-
<script src="
|
|
15
|
-
<script src="
|
|
13
|
+
<script src="../../_vendor/react/react.production.min.js"></script>
|
|
14
|
+
<script src="../../_vendor/react/react-dom.production.min.js"></script>
|
|
15
|
+
<script src="../../_vendor/babel/babel.min.js"></script>
|
|
16
16
|
<script src="../../_ds_bundle.js"></script>
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
body { margin: 0; background: var(--cs-color-surface-page); padding: 22px 24px; }
|
|
10
10
|
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px 28px; max-width: 640px; align-items: start; }
|
|
11
11
|
</style>
|
|
12
|
-
<script src="
|
|
13
|
-
<script src="
|
|
14
|
-
<script src="
|
|
12
|
+
<script src="../../_vendor/react/react.production.min.js"></script>
|
|
13
|
+
<script src="../../_vendor/react/react-dom.production.min.js"></script>
|
|
14
|
+
<script src="../../_vendor/babel/babel.min.js"></script>
|
|
15
15
|
<script src="../../_ds_bundle.js"></script>
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
@@ -6,7 +6,7 @@ export type IconName =
|
|
|
6
6
|
| "search" | "sliders" | "upload" | "download" | "calendar"
|
|
7
7
|
| "user" | "plus" | "trash" | "external" | "menu"
|
|
8
8
|
| "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right"
|
|
9
|
-
| "edit" | "copy" | "info" | "alert-triangle";
|
|
9
|
+
| "edit" | "copy" | "info" | "alert-triangle" | "pin";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* CyberSkill line-icon renderer. One component drives the whole in-repo icon set
|
package/components/icon/Icon.jsx
CHANGED
|
@@ -49,6 +49,7 @@ export const CS_ICONS = {
|
|
|
49
49
|
copy: { viewBox: "0 0 24 24", els: [["rect", { x: 8, y: 8, width: 12, height: 12, rx: 2 }], ["path", { d: "M4 16V6a2 2 0 0 1 2-2h10" }]] },
|
|
50
50
|
info: { viewBox: "0 0 24 24", els: [["circle", { cx: 12, cy: 12, r: 9 }], ["path", { d: "M12 11v5M12 7.75v.01" }]] },
|
|
51
51
|
"alert-triangle": { viewBox: "0 0 24 24", els: [["path", { d: "M12 3.5l9 16H3z" }], ["path", { d: "M12 10v4M12 17.5v.01" }]] },
|
|
52
|
+
pin: { viewBox: "0 0 24 24", els: [["path", { d: "M12 21v-7" }], ["path", { d: "M8.5 3.5h7l-1.2 6.5h2.7L12 14.5 6.999 10h2.7z" }]] },
|
|
52
53
|
};
|
|
53
54
|
|
|
54
55
|
export function Icon({ name, size = "md", label, className, strokeWidth = 1.75, ...props }) {
|
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
<Icon name="sparkle" size="lg" label="Wish" /> {/* meaningful */}
|
|
6
6
|
```
|
|
7
7
|
|
|
8
|
-
Set: `close · sun · moon · arrow-right · check · sparkle · chat · sound-on · sound-off` + v2.0 extension `search · sliders · upload · download · calendar · user · plus · trash · external · menu` + v2.13 `chevron-down/up/left/right · edit · copy · info · alert-triangle` (same grammar). `sparkle` is the brand's "wish" glyph. Colour follows the surrounding text token — set `color` on a parent to recolour.
|
|
8
|
+
Set: `close · sun · moon · arrow-right · check · sparkle · chat · sound-on · sound-off` + v2.0 extension `search · sliders · upload · download · calendar · user · plus · trash · external · menu` + v2.13 `chevron-down/up/left/right · edit · copy · info · alert-triangle · pin` (same grammar). `sparkle` is the brand's "wish" glyph. Colour follows the surrounding text token — set `color` on a parent to recolour.
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
.cell .g { color: var(--cs-color-brand-umber); }
|
|
14
14
|
.cell:nth-child(6) .g { color: var(--cs-color-brand-ochre); }
|
|
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>
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
.lockup b { font: 800 22px/1 var(--cs-font-family-ui); color: var(--cs-color-brand-umber); letter-spacing: -.01em; }
|
|
16
16
|
.cap { font: 500 12px/1.4 var(--cs-font-family-ui); color: var(--cs-color-text-muted); }
|
|
17
17
|
</style>
|
|
18
|
-
<script src="
|
|
19
|
-
<script src="
|
|
20
|
-
<script src="
|
|
18
|
+
<script src="../../_vendor/react/react.production.min.js"></script>
|
|
19
|
+
<script src="../../_vendor/react/react-dom.production.min.js"></script>
|
|
20
|
+
<script src="../../_vendor/babel/babel.min.js"></script>
|
|
21
21
|
<script src="../../_ds_bundle.js"></script>
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
|
@@ -14,6 +14,8 @@ export interface CommandPaletteProps {
|
|
|
14
14
|
onClose?: () => void;
|
|
15
15
|
placeholder?: string;
|
|
16
16
|
groups: CommandGroup[];
|
|
17
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
18
|
+
lang?: string;
|
|
17
19
|
className?: string;
|
|
18
20
|
}
|
|
19
21
|
export function CommandPalette(props: CommandPaletteProps): React.ReactElement | null;
|
|
@@ -1,23 +1,38 @@
|
|
|
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 "../overlays/OverlayManager.jsx";
|
|
4
5
|
|
|
5
6
|
/** CyberSkill CommandPalette — ⌘K overlay with search + grouped actions. Controlled via open/onClose. */
|
|
6
7
|
export function CommandPalette({ open, onClose, placeholder, groups = [], lang, className }) {
|
|
7
8
|
const [q, setQ] = React.useState("");
|
|
8
|
-
React.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
+
preferFocusSelector: ".cs-cmdk__search input",
|
|
18
|
+
onEscape: () => closeRef.current && closeRef.current(),
|
|
19
|
+
panelRef: panel,
|
|
20
|
+
});
|
|
21
|
+
|
|
14
22
|
const [ref, L] = useLang(lang);
|
|
15
23
|
const t = makeT("CommandPalette", L);
|
|
16
24
|
const ph = placeholder != null ? placeholder : t("placeholder");
|
|
17
25
|
if (!open) return null;
|
|
18
26
|
const needle = q.trim().toLowerCase();
|
|
19
27
|
return (
|
|
20
|
-
<div
|
|
28
|
+
<div
|
|
29
|
+
ref={(el) => {
|
|
30
|
+
ref.current = el;
|
|
31
|
+
panel.current = el;
|
|
32
|
+
}}
|
|
33
|
+
className="cs-cmdk-scrim"
|
|
34
|
+
onClick={onClose}
|
|
35
|
+
>
|
|
21
36
|
<div className={cx("cs-cmdk", className)} role="dialog" aria-modal="true" aria-label={t("aria")} onClick={(e) => e.stopPropagation()}>
|
|
22
37
|
<div className="cs-cmdk__search">
|
|
23
38
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7" /><path d="M21 21l-4.3-4.3" /></svg>
|
|
@@ -12,6 +12,8 @@ export interface MenuProps {
|
|
|
12
12
|
align?: "start" | "end";
|
|
13
13
|
open?: boolean;
|
|
14
14
|
onOpenChange?: (open: boolean) => void;
|
|
15
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
16
|
+
lang?: string;
|
|
15
17
|
className?: string;
|
|
16
18
|
}
|
|
17
19
|
export function Menu(props: MenuProps): React.ReactElement;
|