@cyberskill/design 1.1.1 → 1.2.0
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 +25 -3
- package/README.md +3 -3
- package/SKILL.md +3 -3
- package/VERSION +1 -1
- package/_ds_bundle.js +819 -416
- package/_ds_manifest.json +1 -1
- package/_esm/cs.mjs +18 -4
- package/_esm/react.d.ts +2 -0
- package/_esm/react.mjs +1 -0
- package/base/a11y.css +18 -0
- package/base/ai.css +2 -2
- package/base/collections.css +8 -3
- package/base/components.css +11 -2
- package/base/controls.css +61 -48
- package/base/data.css +3 -3
- package/base/feedback.css +5 -0
- package/base/forms.css +9 -3
- package/base/glass.css +6 -0
- package/base/navigation.css +8 -2
- package/base/reset.css +1 -1
- package/base/responsive.css +25 -0
- package/base/shell.css +7 -1
- package/components/_i18n/i18n.js +13 -1
- package/components/_i18n/strings.js +52 -3
- package/components/ai/ConfidenceMeter.jsx +8 -6
- package/components/data/Watermark.jsx +11 -3
- package/components/datatable/DataGrid.jsx +10 -1
- package/components/dialog/Dialog.jsx +13 -45
- package/components/feedback/ProgressBar.jsx +4 -2
- package/components/forms/Cascader.jsx +69 -6
- package/components/forms/Editor.jsx +37 -2
- package/components/forms/FileUpload.jsx +22 -8
- package/components/forms/Switch.jsx +16 -2
- package/components/forms/TimePicker.jsx +3 -1
- package/components/icon/Icon.jsx +1 -0
- package/components/navigation/CommandPalette.jsx +22 -7
- package/components/navigation/Toolbar.jsx +2 -1
- package/components/overlays/AlertDialog.jsx +19 -49
- 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/dist/styles.min.css +2004 -0
- package/docs/benchmark-rubric.md +1 -1
- package/docs/ci-cd.md +3 -1
- package/docs/consuming.md +6 -6
- package/docs/conventions.md +4 -4
- package/docs/decisions/container-query-migration.md +18 -0
- package/docs/decisions/overlay-manager-design.md +101 -0
- package/docs/decisions.md +5 -5
- package/docs/design-styles.md +1 -1
- package/docs/plans/cyberskill-design-system-audit-and-12-month-evolution-plan.md +1490 -0
- package/docs/quality-gates.md +20 -8
- package/docs/release-notes.md +2 -2
- package/docs/status/data/status-feed.json +1 -1
- package/docs/status/index.html +9 -5
- package/docs/status/status-legacy.html +12 -7
- package/docs/sync.md +1 -1
- package/docs/tasks/_state/commit-links.yaml +14 -0
- package/docs/vi/benchmark-rubric.md +1 -1
- package/docs/vi/ci-cd.md +3 -1
- package/docs/vi/consuming.md +6 -6
- package/docs/vi/conventions.md +2 -2
- package/docs/vi/decisions.md +4 -4
- package/docs/vi/quality-gates.md +21 -9
- package/docs/vi/release-notes.md +2 -2
- package/docs/vi/sync.md +1 -1
- package/guidelines/atomic-view.html +11 -7
- package/llms.txt +2 -2
- package/package.json +14 -6
- package/templates/_ds-base.canonical.js +55 -0
- package/templates/ai-cluster-demo.html +2 -2
- package/templates/app-shell/AppShell.dc.html +5 -3
- package/templates/app-shell/ds-base.js +33 -1
- package/templates/app-shell/support.js +13 -20
- package/templates/article/Article.dc.html +5 -1
- package/templates/article/ds-base.js +33 -1
- package/templates/article/support.js +13 -20
- package/templates/auth/Auth.dc.html +10 -5
- package/templates/auth/content-schema.json +12 -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 +7 -3
- package/templates/dashboard/ds-base.js +33 -1
- package/templates/dashboard/support.js +13 -20
- package/templates/delivery-change-note/DeliveryChangeNote.dc.html +2 -1
- 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 +3 -2
- 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/finance-dunning-email/FinanceDunningEmail.dc.html +4 -3
- 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 +4 -3
- package/templates/finance-invoice/ds-base.js +33 -1
- package/templates/finance-invoice/support.js +13 -20
- package/templates/finance-quote/FinanceQuote.dc.html +4 -3
- 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 +4 -3
- 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 +5 -4
- 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 +17 -12
- 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 +5 -1
- 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/elements.css +35 -2
- package/tokens/elevation.css +8 -2
- package/tokens/native/CSTokens.kt +35 -1
- package/tokens/native/CSTokens.swift +35 -1
- package/tokens/native/cs_tokens.dart +35 -1
- package/tokens/provenance.json +12 -12
- package/tokens/spacing.css +2 -0
- package/tokens/tokens.dtcg.json +111 -3
- package/tokens/tokens.js +46 -6
- package/tokens/tokens.json +45 -5
- 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 +4 -0
- 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 +4 -0
- package/ui_kits/website/chat.html +5 -3
- package/ui_kits/website/index.html +3 -3
- package/ui_kits/website/site.css +2 -2
- package/ui_kits/website/work.html +4 -0
package/_ds_bundle.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* @ds-bundle: {"format":4,"namespace":"CyberSkillDesignSystem_847b3c","components":[{"name":"AIDisclosureBadge","sourcePath":"components/ai/AIDisclosureBadge.jsx"},{"name":"ChatMessage","sourcePath":"components/ai/ChatMessage.jsx"},{"name":"CitationList","sourcePath":"components/ai/CitationList.jsx"},{"name":"ConfidenceMeter","sourcePath":"components/ai/ConfidenceMeter.jsx"},{"name":"HumanReviewGate","sourcePath":"components/ai/HumanReviewGate.jsx"},{"name":"PromptInput","sourcePath":"components/ai/PromptInput.jsx"},{"name":"PromptSuggestions","sourcePath":"components/ai/PromptSuggestions.jsx"},{"name":"TypingIndicator","sourcePath":"components/ai/TypingIndicator.jsx"},{"name":"LumiAvatar","sourcePath":"components/brand/LumiAvatar.jsx"},{"name":"Button","sourcePath":"components/button/Button.jsx"},{"name":"ButtonGroup","sourcePath":"components/button/ButtonGroup.jsx"},{"name":"FloatingActionButton","sourcePath":"components/button/FloatingActionButton.jsx"},{"name":"Accordion","sourcePath":"components/data/Accordion.jsx"},{"name":"AspectRatio","sourcePath":"components/data/AspectRatio.jsx"},{"name":"Avatar","sourcePath":"components/data/Avatar.jsx"},{"name":"AvatarGroup","sourcePath":"components/data/Avatar.jsx"},{"name":"Card","sourcePath":"components/data/Card.jsx"},{"name":"CardHeader","sourcePath":"components/data/Card.jsx"},{"name":"CardBody","sourcePath":"components/data/Card.jsx"},{"name":"CardFooter","sourcePath":"components/data/Card.jsx"},{"name":"Carousel","sourcePath":"components/data/Carousel.jsx"},{"name":"Chart","sourcePath":"components/data/Chart.jsx"},{"name":"CodeBlock","sourcePath":"components/data/CodeBlock.jsx"},{"name":"Collapsible","sourcePath":"components/data/Collapsible.jsx"},{"name":"Comment","sourcePath":"components/data/Comment.jsx"},{"name":"DescriptionList","sourcePath":"components/data/DescriptionList.jsx"},{"name":"Divider","sourcePath":"components/data/Divider.jsx"},{"name":"Image","sourcePath":"components/data/Image.jsx"},{"name":"Item","sourcePath":"components/data/Item.jsx"},{"name":"Kbd","sourcePath":"components/data/Kbd.jsx"},{"name":"List","sourcePath":"components/data/List.jsx"},{"name":"ListItem","sourcePath":"components/data/List.jsx"},{"name":"Masonry","sourcePath":"components/data/Masonry.jsx"},{"name":"QRCode","sourcePath":"components/data/QRCode.jsx"},{"name":"ScrollArea","sourcePath":"components/data/ScrollArea.jsx"},{"name":"Sortable","sourcePath":"components/data/Sortable.jsx"},{"name":"Splitter","sourcePath":"components/data/Splitter.jsx"},{"name":"Stat","sourcePath":"components/data/Stat.jsx"},{"name":"Terminal","sourcePath":"components/data/Terminal.jsx"},{"name":"Timeline","sourcePath":"components/data/Timeline.jsx"},{"name":"Tooltip","sourcePath":"components/data/Tooltip.jsx"},{"name":"Tree","sourcePath":"components/data/Tree.jsx"},{"name":"Watermark","sourcePath":"components/data/Watermark.jsx"},{"name":"DataGrid","sourcePath":"components/datatable/DataGrid.jsx"},{"name":"DataTable","sourcePath":"components/datatable/DataTable.jsx"},{"name":"TreeTable","sourcePath":"components/datatable/TreeTable.jsx"},{"name":"Dialog","sourcePath":"components/dialog/Dialog.jsx"},{"name":"Alert","sourcePath":"components/feedback/Alert.jsx"},{"name":"Badge","sourcePath":"components/feedback/Badge.jsx"},{"name":"EmptyState","sourcePath":"components/feedback/EmptyState.jsx"},{"name":"ProgressBar","sourcePath":"components/feedback/ProgressBar.jsx"},{"name":"Result","sourcePath":"components/feedback/Result.jsx"},{"name":"Skeleton","sourcePath":"components/feedback/Skeleton.jsx"},{"name":"Spinner","sourcePath":"components/feedback/Spinner.jsx"},{"name":"StatusIndicator","sourcePath":"components/feedback/StatusIndicator.jsx"},{"name":"Tag","sourcePath":"components/feedback/Tag.jsx"},{"name":"ToastStack","sourcePath":"components/feedback/Toast.jsx"},{"name":"Toast","sourcePath":"components/feedback/Toast.jsx"},{"name":"Calendar","sourcePath":"components/forms/Calendar.jsx"},{"name":"Cascader","sourcePath":"components/forms/Cascader.jsx"},{"name":"Checkbox","sourcePath":"components/forms/Checkbox.jsx"},{"name":"ColorPicker","sourcePath":"components/forms/ColorPicker.jsx"},{"name":"Combobox","sourcePath":"components/forms/Combobox.jsx"},{"name":"DatePicker","sourcePath":"components/forms/DatePicker.jsx"},{"name":"Editor","sourcePath":"components/forms/Editor.jsx"},{"name":"FileUpload","sourcePath":"components/forms/FileUpload.jsx"},{"name":"Form","sourcePath":"components/forms/Form.jsx"},{"name":"FormField","sourcePath":"components/forms/Form.jsx"},{"name":"FormFieldArray","sourcePath":"components/forms/Form.jsx"},{"name":"FormWizard","sourcePath":"components/forms/Form.jsx"},{"name":"InlineEdit","sourcePath":"components/forms/InlineEdit.jsx"},{"name":"InputGroup","sourcePath":"components/forms/InputGroup.jsx"},{"name":"InputOTP","sourcePath":"components/forms/InputOTP.jsx"},{"name":"Mentions","sourcePath":"components/forms/Mentions.jsx"},{"name":"NativeSelect","sourcePath":"components/forms/NativeSelect.jsx"},{"name":"NumberField","sourcePath":"components/forms/NumberField.jsx"},{"name":"Radio","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"RadioGroup","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"Rating","sourcePath":"components/forms/Rating.jsx"},{"name":"SearchField","sourcePath":"components/forms/SearchField.jsx"},{"name":"SegmentedControl","sourcePath":"components/forms/SegmentedControl.jsx"},{"name":"Select","sourcePath":"components/forms/Select.jsx"},{"name":"Slider","sourcePath":"components/forms/Slider.jsx"},{"name":"Switch","sourcePath":"components/forms/Switch.jsx"},{"name":"TagInput","sourcePath":"components/forms/TagInput.jsx"},{"name":"Textarea","sourcePath":"components/forms/Textarea.jsx"},{"name":"TimePicker","sourcePath":"components/forms/TimePicker.jsx"},{"name":"Toggle","sourcePath":"components/forms/Toggle.jsx"},{"name":"Transfer","sourcePath":"components/forms/Transfer.jsx"},{"name":"TreeSelect","sourcePath":"components/forms/TreeSelect.jsx"},{"name":"CS_ICONS","sourcePath":"components/icon/Icon.jsx"},{"name":"Icon","sourcePath":"components/icon/Icon.jsx"},{"name":"Logo","sourcePath":"components/logo/Logo.jsx"},{"name":"CS_LOGO_VIEWBOX","sourcePath":"components/logo/logo-data.js"},{"name":"CS_LOGO_MARK_INNER","sourcePath":"components/logo/logo-data.js"},{"name":"Anchor","sourcePath":"components/navigation/Anchor.jsx"},{"name":"BackTop","sourcePath":"components/navigation/BackTop.jsx"},{"name":"Breadcrumb","sourcePath":"components/navigation/Breadcrumb.jsx"},{"name":"CommandPalette","sourcePath":"components/navigation/CommandPalette.jsx"},{"name":"Dock","sourcePath":"components/navigation/Dock.jsx"},{"name":"HotKeys","sourcePath":"components/navigation/HotKeys.jsx"},{"name":"Link","sourcePath":"components/navigation/Link.jsx"},{"name":"Menu","sourcePath":"components/navigation/Menu.jsx"},{"name":"MenuItem","sourcePath":"components/navigation/Menu.jsx"},{"name":"Menubar","sourcePath":"components/navigation/Menubar.jsx"},{"name":"NavigationMenu","sourcePath":"components/navigation/NavigationMenu.jsx"},{"name":"Pagination","sourcePath":"components/navigation/Pagination.jsx"},{"name":"Sidebar","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"NavItem","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"Steps","sourcePath":"components/navigation/Steps.jsx"},{"name":"Tabs","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Tab","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Toolbar","sourcePath":"components/navigation/Toolbar.jsx"},{"name":"AlertDialog","sourcePath":"components/overlays/AlertDialog.jsx"},{"name":"ContextMenu","sourcePath":"components/overlays/ContextMenu.jsx"},{"name":"Drawer","sourcePath":"components/overlays/Drawer.jsx"},{"name":"HoverCard","sourcePath":"components/overlays/HoverCard.jsx"},{"name":"Popconfirm","sourcePath":"components/overlays/Popconfirm.jsx"},{"name":"Popover","sourcePath":"components/overlays/Popover.jsx"},{"name":"Tour","sourcePath":"components/overlays/Tour.jsx"},{"name":"TextField","sourcePath":"components/textfield/TextField.jsx"}],"sourceHashes":{"components/_i18n/i18n.js":"c6c51a65bd79","components/_i18n/strings.js":"73bc5837fc8e","components/_utils/cx.js":"ad6a747ea116","components/ai/AIDisclosureBadge.jsx":"4c8954aa2d79","components/ai/ChatMessage.jsx":"84076f3488f2","components/ai/CitationList.jsx":"4d12ef868ff3","components/ai/ConfidenceMeter.jsx":"24e43b7f7a47","components/ai/HumanReviewGate.jsx":"922b278dca5c","components/ai/PromptInput.jsx":"7634643dafa5","components/ai/PromptSuggestions.jsx":"02d64117ecfa","components/ai/TypingIndicator.jsx":"149e3a0c7ef8","components/brand/LumiAvatar.jsx":"b6444360cf80","components/button/Button.jsx":"6d902a925eed","components/button/ButtonGroup.jsx":"1a1481f6fb93","components/button/FloatingActionButton.jsx":"ce49fe4129a3","components/data/Accordion.jsx":"fed81278cefd","components/data/AspectRatio.jsx":"6c1e8703891e","components/data/Avatar.jsx":"88c8f59334e6","components/data/Card.jsx":"96e1f9ef44a9","components/data/Carousel.jsx":"caf09a766c42","components/data/Chart.jsx":"1953e9fef120","components/data/CodeBlock.jsx":"04e0bd2507e2","components/data/Collapsible.jsx":"3d961fef83f8","components/data/Comment.jsx":"81469a910d80","components/data/DescriptionList.jsx":"ce50d72546bb","components/data/Divider.jsx":"2d08b4a7b18e","components/data/Image.jsx":"da5c7d4c69af","components/data/Item.jsx":"7e1ac68c4e96","components/data/Kbd.jsx":"3b3d867cbdd8","components/data/List.jsx":"5c221b19efe0","components/data/Masonry.jsx":"a65508731d79","components/data/QRCode.jsx":"6acaf577a7fc","components/data/ScrollArea.jsx":"c2e2ec304b1e","components/data/Sortable.jsx":"315b50256128","components/data/Splitter.jsx":"d231064601e9","components/data/Stat.jsx":"35734a801a71","components/data/Terminal.jsx":"3a3cd4477814","components/data/Timeline.jsx":"22058a781a98","components/data/Tooltip.jsx":"4d027aff5559","components/data/Tree.jsx":"9097456de50f","components/data/Watermark.jsx":"4be0b6230d47","components/data/qr-encode.js":"14e8de77df5f","components/datatable/DataGrid.jsx":"e4aa4a47d05e","components/datatable/DataTable.jsx":"fbfad5570592","components/datatable/TreeTable.jsx":"597c35135ebb","components/dialog/Dialog.jsx":"7af51ee28ab6","components/feedback/Alert.jsx":"0bbe4e5f467a","components/feedback/Badge.jsx":"e691ae1634f8","components/feedback/EmptyState.jsx":"9a9c00523cec","components/feedback/ProgressBar.jsx":"1a66335d5d9e","components/feedback/Result.jsx":"c168f8dcb009","components/feedback/Skeleton.jsx":"86ee345cb412","components/feedback/Spinner.jsx":"cad2ed4008a6","components/feedback/StatusIndicator.jsx":"d27a5fc3db2a","components/feedback/Tag.jsx":"13d288da9f38","components/feedback/Toast.jsx":"38cc9a82ede9","components/forms/Calendar.jsx":"8a66cbe766af","components/forms/Cascader.jsx":"ada31ccaf716","components/forms/Checkbox.jsx":"2badb7b3b72b","components/forms/ColorPicker.jsx":"d04db0ee7678","components/forms/Combobox.jsx":"3f2fb4d28922","components/forms/DatePicker.jsx":"7a6c18e1e635","components/forms/Editor.jsx":"d7bed6e52cff","components/forms/FileUpload.jsx":"e8031a109093","components/forms/Form.jsx":"f7952da4b73a","components/forms/InlineEdit.jsx":"5ffb40598769","components/forms/InputGroup.jsx":"06d6c22420d0","components/forms/InputOTP.jsx":"c3a5d02ffebc","components/forms/Mentions.jsx":"04bc4b5a4ace","components/forms/NativeSelect.jsx":"d6f6d300f75d","components/forms/NumberField.jsx":"44975fd25721","components/forms/RadioGroup.jsx":"1a64f7600e01","components/forms/Rating.jsx":"06d345ecc5f4","components/forms/SearchField.jsx":"2a12c65900ec","components/forms/SegmentedControl.jsx":"1f143c62fb56","components/forms/Select.jsx":"1b5ba905b339","components/forms/Slider.jsx":"69aa1a5f1af8","components/forms/Switch.jsx":"0b37cfa41979","components/forms/TagInput.jsx":"2d1554422097","components/forms/Textarea.jsx":"cf244fee0e37","components/forms/TimePicker.jsx":"165192c8760c","components/forms/Toggle.jsx":"338453a34669","components/forms/Transfer.jsx":"dd0c02d1014e","components/forms/TreeSelect.jsx":"a5b1b91d1d6a","components/icon/Icon.jsx":"379dc6de903e","components/logo/Logo.jsx":"445c5f5fbd40","components/logo/logo-data.js":"f1a251a50c8f","components/navigation/Anchor.jsx":"491fb330e718","components/navigation/BackTop.jsx":"5cac0081fc20","components/navigation/Breadcrumb.jsx":"45636f3b0a51","components/navigation/CommandPalette.jsx":"2b5b30906b8b","components/navigation/Dock.jsx":"3073e2870c65","components/navigation/HotKeys.jsx":"f0f707a3335d","components/navigation/Link.jsx":"d4fe3fcffd2c","components/navigation/Menu.jsx":"6786788f13f8","components/navigation/Menubar.jsx":"1aa64f59891e","components/navigation/NavigationMenu.jsx":"020279fd7f79","components/navigation/Pagination.jsx":"a1fc19bfd104","components/navigation/Sidebar.jsx":"d578b013ad33","components/navigation/Steps.jsx":"85cb20bd45da","components/navigation/Tabs.jsx":"5d5921da1644","components/navigation/Toolbar.jsx":"9727d7bdbc5f","components/overlays/AlertDialog.jsx":"2ed7fbde4a5a","components/overlays/ContextMenu.jsx":"e7e3386d89ac","components/overlays/Drawer.jsx":"8227143abbfa","components/overlays/HoverCard.jsx":"5cfabde80960","components/overlays/Popconfirm.jsx":"55f08dba5f38","components/overlays/Popover.jsx":"1582f7fa5533","components/overlays/Tour.jsx":"9901ee649da0","components/textfield/TextField.jsx":"c06bd9729f20","image-slot.js":"0394ad34f685","tokens/tokens.js":"02cfbae229ac","ui_kits/status-hub/StatusHub.jsx":"88dfd93e1664","ui_kits/status-hub/data.js":"664bbbb30cb3","ui_kits/website/Website.jsx":"c3a0938d9279","ui_kits/website/copy.js":"9d42c52c17cb"},"inlinedExternals":[],"unexposedExports":[{"name":"cx","sourcePath":"components/_utils/cx.js"},{"name":"formatCurrency","sourcePath":"components/_i18n/i18n.js"},{"name":"formatDate","sourcePath":"components/_i18n/i18n.js"},{"name":"formatNumber","sourcePath":"components/_i18n/i18n.js"},{"name":"getPath","sourcePath":"components/forms/Form.jsx"},{"name":"makeT","sourcePath":"components/_i18n/i18n.js"},{"name":"monthName","sourcePath":"components/_i18n/i18n.js"},{"name":"qrMatrix","sourcePath":"components/data/qr-encode.js"},{"name":"resolveLang","sourcePath":"components/_i18n/i18n.js"},{"name":"setPath","sourcePath":"components/forms/Form.jsx"},{"name":"strings","sourcePath":"components/_i18n/strings.js"},{"name":"tokens","sourcePath":"tokens/tokens.js"},{"name":"tr","sourcePath":"components/_i18n/i18n.js"},{"name":"useLang","sourcePath":"components/_i18n/i18n.js"}]} */
|
|
1
|
+
/* @ds-bundle: {"format":4,"namespace":"CyberSkillDesignSystem_847b3c","components":[{"name":"AIDisclosureBadge","sourcePath":"components/ai/AIDisclosureBadge.jsx"},{"name":"ChatMessage","sourcePath":"components/ai/ChatMessage.jsx"},{"name":"CitationList","sourcePath":"components/ai/CitationList.jsx"},{"name":"ConfidenceMeter","sourcePath":"components/ai/ConfidenceMeter.jsx"},{"name":"HumanReviewGate","sourcePath":"components/ai/HumanReviewGate.jsx"},{"name":"PromptInput","sourcePath":"components/ai/PromptInput.jsx"},{"name":"PromptSuggestions","sourcePath":"components/ai/PromptSuggestions.jsx"},{"name":"TypingIndicator","sourcePath":"components/ai/TypingIndicator.jsx"},{"name":"LumiAvatar","sourcePath":"components/brand/LumiAvatar.jsx"},{"name":"Button","sourcePath":"components/button/Button.jsx"},{"name":"ButtonGroup","sourcePath":"components/button/ButtonGroup.jsx"},{"name":"FloatingActionButton","sourcePath":"components/button/FloatingActionButton.jsx"},{"name":"Accordion","sourcePath":"components/data/Accordion.jsx"},{"name":"AspectRatio","sourcePath":"components/data/AspectRatio.jsx"},{"name":"Avatar","sourcePath":"components/data/Avatar.jsx"},{"name":"AvatarGroup","sourcePath":"components/data/Avatar.jsx"},{"name":"Card","sourcePath":"components/data/Card.jsx"},{"name":"CardHeader","sourcePath":"components/data/Card.jsx"},{"name":"CardBody","sourcePath":"components/data/Card.jsx"},{"name":"CardFooter","sourcePath":"components/data/Card.jsx"},{"name":"Carousel","sourcePath":"components/data/Carousel.jsx"},{"name":"Chart","sourcePath":"components/data/Chart.jsx"},{"name":"CodeBlock","sourcePath":"components/data/CodeBlock.jsx"},{"name":"Collapsible","sourcePath":"components/data/Collapsible.jsx"},{"name":"Comment","sourcePath":"components/data/Comment.jsx"},{"name":"DescriptionList","sourcePath":"components/data/DescriptionList.jsx"},{"name":"Divider","sourcePath":"components/data/Divider.jsx"},{"name":"Image","sourcePath":"components/data/Image.jsx"},{"name":"Item","sourcePath":"components/data/Item.jsx"},{"name":"Kbd","sourcePath":"components/data/Kbd.jsx"},{"name":"List","sourcePath":"components/data/List.jsx"},{"name":"ListItem","sourcePath":"components/data/List.jsx"},{"name":"Masonry","sourcePath":"components/data/Masonry.jsx"},{"name":"QRCode","sourcePath":"components/data/QRCode.jsx"},{"name":"ScrollArea","sourcePath":"components/data/ScrollArea.jsx"},{"name":"Sortable","sourcePath":"components/data/Sortable.jsx"},{"name":"Splitter","sourcePath":"components/data/Splitter.jsx"},{"name":"Stat","sourcePath":"components/data/Stat.jsx"},{"name":"Terminal","sourcePath":"components/data/Terminal.jsx"},{"name":"Timeline","sourcePath":"components/data/Timeline.jsx"},{"name":"Tooltip","sourcePath":"components/data/Tooltip.jsx"},{"name":"Tree","sourcePath":"components/data/Tree.jsx"},{"name":"Watermark","sourcePath":"components/data/Watermark.jsx"},{"name":"DataGrid","sourcePath":"components/datatable/DataGrid.jsx"},{"name":"DataTable","sourcePath":"components/datatable/DataTable.jsx"},{"name":"TreeTable","sourcePath":"components/datatable/TreeTable.jsx"},{"name":"Dialog","sourcePath":"components/dialog/Dialog.jsx"},{"name":"Alert","sourcePath":"components/feedback/Alert.jsx"},{"name":"Badge","sourcePath":"components/feedback/Badge.jsx"},{"name":"EmptyState","sourcePath":"components/feedback/EmptyState.jsx"},{"name":"ProgressBar","sourcePath":"components/feedback/ProgressBar.jsx"},{"name":"Result","sourcePath":"components/feedback/Result.jsx"},{"name":"Skeleton","sourcePath":"components/feedback/Skeleton.jsx"},{"name":"Spinner","sourcePath":"components/feedback/Spinner.jsx"},{"name":"StatusIndicator","sourcePath":"components/feedback/StatusIndicator.jsx"},{"name":"Tag","sourcePath":"components/feedback/Tag.jsx"},{"name":"ToastStack","sourcePath":"components/feedback/Toast.jsx"},{"name":"Toast","sourcePath":"components/feedback/Toast.jsx"},{"name":"Calendar","sourcePath":"components/forms/Calendar.jsx"},{"name":"Cascader","sourcePath":"components/forms/Cascader.jsx"},{"name":"Checkbox","sourcePath":"components/forms/Checkbox.jsx"},{"name":"ColorPicker","sourcePath":"components/forms/ColorPicker.jsx"},{"name":"Combobox","sourcePath":"components/forms/Combobox.jsx"},{"name":"DatePicker","sourcePath":"components/forms/DatePicker.jsx"},{"name":"Editor","sourcePath":"components/forms/Editor.jsx"},{"name":"FileUpload","sourcePath":"components/forms/FileUpload.jsx"},{"name":"Form","sourcePath":"components/forms/Form.jsx"},{"name":"FormField","sourcePath":"components/forms/Form.jsx"},{"name":"FormFieldArray","sourcePath":"components/forms/Form.jsx"},{"name":"FormWizard","sourcePath":"components/forms/Form.jsx"},{"name":"InlineEdit","sourcePath":"components/forms/InlineEdit.jsx"},{"name":"InputGroup","sourcePath":"components/forms/InputGroup.jsx"},{"name":"InputOTP","sourcePath":"components/forms/InputOTP.jsx"},{"name":"Mentions","sourcePath":"components/forms/Mentions.jsx"},{"name":"NativeSelect","sourcePath":"components/forms/NativeSelect.jsx"},{"name":"NumberField","sourcePath":"components/forms/NumberField.jsx"},{"name":"Radio","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"RadioGroup","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"Rating","sourcePath":"components/forms/Rating.jsx"},{"name":"SearchField","sourcePath":"components/forms/SearchField.jsx"},{"name":"SegmentedControl","sourcePath":"components/forms/SegmentedControl.jsx"},{"name":"Select","sourcePath":"components/forms/Select.jsx"},{"name":"Slider","sourcePath":"components/forms/Slider.jsx"},{"name":"Switch","sourcePath":"components/forms/Switch.jsx"},{"name":"TagInput","sourcePath":"components/forms/TagInput.jsx"},{"name":"Textarea","sourcePath":"components/forms/Textarea.jsx"},{"name":"TimePicker","sourcePath":"components/forms/TimePicker.jsx"},{"name":"Toggle","sourcePath":"components/forms/Toggle.jsx"},{"name":"Transfer","sourcePath":"components/forms/Transfer.jsx"},{"name":"TreeSelect","sourcePath":"components/forms/TreeSelect.jsx"},{"name":"CS_ICONS","sourcePath":"components/icon/Icon.jsx"},{"name":"Icon","sourcePath":"components/icon/Icon.jsx"},{"name":"Logo","sourcePath":"components/logo/Logo.jsx"},{"name":"CS_LOGO_VIEWBOX","sourcePath":"components/logo/logo-data.js"},{"name":"CS_LOGO_MARK_INNER","sourcePath":"components/logo/logo-data.js"},{"name":"Anchor","sourcePath":"components/navigation/Anchor.jsx"},{"name":"BackTop","sourcePath":"components/navigation/BackTop.jsx"},{"name":"Breadcrumb","sourcePath":"components/navigation/Breadcrumb.jsx"},{"name":"CommandPalette","sourcePath":"components/navigation/CommandPalette.jsx"},{"name":"Dock","sourcePath":"components/navigation/Dock.jsx"},{"name":"HotKeys","sourcePath":"components/navigation/HotKeys.jsx"},{"name":"Link","sourcePath":"components/navigation/Link.jsx"},{"name":"Menu","sourcePath":"components/navigation/Menu.jsx"},{"name":"MenuItem","sourcePath":"components/navigation/Menu.jsx"},{"name":"Menubar","sourcePath":"components/navigation/Menubar.jsx"},{"name":"NavigationMenu","sourcePath":"components/navigation/NavigationMenu.jsx"},{"name":"Pagination","sourcePath":"components/navigation/Pagination.jsx"},{"name":"Sidebar","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"NavItem","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"Steps","sourcePath":"components/navigation/Steps.jsx"},{"name":"Tabs","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Tab","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Toolbar","sourcePath":"components/navigation/Toolbar.jsx"},{"name":"AlertDialog","sourcePath":"components/overlays/AlertDialog.jsx"},{"name":"ContextMenu","sourcePath":"components/overlays/ContextMenu.jsx"},{"name":"Drawer","sourcePath":"components/overlays/Drawer.jsx"},{"name":"HoverCard","sourcePath":"components/overlays/HoverCard.jsx"},{"name":"OverlayProvider","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"Popconfirm","sourcePath":"components/overlays/Popconfirm.jsx"},{"name":"Popover","sourcePath":"components/overlays/Popover.jsx"},{"name":"Tour","sourcePath":"components/overlays/Tour.jsx"},{"name":"TextField","sourcePath":"components/textfield/TextField.jsx"}],"sourceHashes":{"components/_i18n/i18n.js":"63f973d61113","components/_i18n/strings.js":"cea7ef153e18","components/_utils/cx.js":"ad6a747ea116","components/ai/AIDisclosureBadge.jsx":"4c8954aa2d79","components/ai/ChatMessage.jsx":"84076f3488f2","components/ai/CitationList.jsx":"4d12ef868ff3","components/ai/ConfidenceMeter.jsx":"68cf2bba3a9e","components/ai/HumanReviewGate.jsx":"922b278dca5c","components/ai/PromptInput.jsx":"7634643dafa5","components/ai/PromptSuggestions.jsx":"02d64117ecfa","components/ai/TypingIndicator.jsx":"149e3a0c7ef8","components/brand/LumiAvatar.jsx":"b6444360cf80","components/button/Button.jsx":"6d902a925eed","components/button/ButtonGroup.jsx":"1a1481f6fb93","components/button/FloatingActionButton.jsx":"ce49fe4129a3","components/data/Accordion.jsx":"fed81278cefd","components/data/AspectRatio.jsx":"6c1e8703891e","components/data/Avatar.jsx":"88c8f59334e6","components/data/Card.jsx":"96e1f9ef44a9","components/data/Carousel.jsx":"caf09a766c42","components/data/Chart.jsx":"1953e9fef120","components/data/CodeBlock.jsx":"04e0bd2507e2","components/data/Collapsible.jsx":"3d961fef83f8","components/data/Comment.jsx":"81469a910d80","components/data/DescriptionList.jsx":"ce50d72546bb","components/data/Divider.jsx":"2d08b4a7b18e","components/data/Image.jsx":"da5c7d4c69af","components/data/Item.jsx":"7e1ac68c4e96","components/data/Kbd.jsx":"3b3d867cbdd8","components/data/List.jsx":"5c221b19efe0","components/data/Masonry.jsx":"a65508731d79","components/data/QRCode.jsx":"6acaf577a7fc","components/data/ScrollArea.jsx":"c2e2ec304b1e","components/data/Sortable.jsx":"315b50256128","components/data/Splitter.jsx":"d231064601e9","components/data/Stat.jsx":"35734a801a71","components/data/Terminal.jsx":"3a3cd4477814","components/data/Timeline.jsx":"22058a781a98","components/data/Tooltip.jsx":"4d027aff5559","components/data/Tree.jsx":"9097456de50f","components/data/Watermark.jsx":"66b7b71488d8","components/data/qr-encode.js":"14e8de77df5f","components/datatable/DataGrid.jsx":"c84fe5d5b8cc","components/datatable/DataTable.jsx":"fbfad5570592","components/datatable/TreeTable.jsx":"597c35135ebb","components/dialog/Dialog.jsx":"8ef7722c37c4","components/feedback/Alert.jsx":"0bbe4e5f467a","components/feedback/Badge.jsx":"e691ae1634f8","components/feedback/EmptyState.jsx":"9a9c00523cec","components/feedback/ProgressBar.jsx":"3986118b0da8","components/feedback/Result.jsx":"c168f8dcb009","components/feedback/Skeleton.jsx":"86ee345cb412","components/feedback/Spinner.jsx":"cad2ed4008a6","components/feedback/StatusIndicator.jsx":"d27a5fc3db2a","components/feedback/Tag.jsx":"13d288da9f38","components/feedback/Toast.jsx":"38cc9a82ede9","components/forms/Calendar.jsx":"8a66cbe766af","components/forms/Cascader.jsx":"7b830b11edb1","components/forms/Checkbox.jsx":"2badb7b3b72b","components/forms/ColorPicker.jsx":"d04db0ee7678","components/forms/Combobox.jsx":"3f2fb4d28922","components/forms/DatePicker.jsx":"7a6c18e1e635","components/forms/Editor.jsx":"194484fb9dc4","components/forms/FileUpload.jsx":"509dfaff8bea","components/forms/Form.jsx":"f7952da4b73a","components/forms/InlineEdit.jsx":"5ffb40598769","components/forms/InputGroup.jsx":"06d6c22420d0","components/forms/InputOTP.jsx":"c3a5d02ffebc","components/forms/Mentions.jsx":"04bc4b5a4ace","components/forms/NativeSelect.jsx":"d6f6d300f75d","components/forms/NumberField.jsx":"44975fd25721","components/forms/RadioGroup.jsx":"1a64f7600e01","components/forms/Rating.jsx":"06d345ecc5f4","components/forms/SearchField.jsx":"2a12c65900ec","components/forms/SegmentedControl.jsx":"1f143c62fb56","components/forms/Select.jsx":"1b5ba905b339","components/forms/Slider.jsx":"69aa1a5f1af8","components/forms/Switch.jsx":"ed54f4bceb60","components/forms/TagInput.jsx":"2d1554422097","components/forms/Textarea.jsx":"cf244fee0e37","components/forms/TimePicker.jsx":"abd6e54b2983","components/forms/Toggle.jsx":"338453a34669","components/forms/Transfer.jsx":"dd0c02d1014e","components/forms/TreeSelect.jsx":"a5b1b91d1d6a","components/icon/Icon.jsx":"280fba8477db","components/logo/Logo.jsx":"445c5f5fbd40","components/logo/logo-data.js":"f1a251a50c8f","components/navigation/Anchor.jsx":"491fb330e718","components/navigation/BackTop.jsx":"5cac0081fc20","components/navigation/Breadcrumb.jsx":"45636f3b0a51","components/navigation/CommandPalette.jsx":"51c25b8416eb","components/navigation/Dock.jsx":"3073e2870c65","components/navigation/HotKeys.jsx":"f0f707a3335d","components/navigation/Link.jsx":"d4fe3fcffd2c","components/navigation/Menu.jsx":"6786788f13f8","components/navigation/Menubar.jsx":"1aa64f59891e","components/navigation/NavigationMenu.jsx":"020279fd7f79","components/navigation/Pagination.jsx":"a1fc19bfd104","components/navigation/Sidebar.jsx":"d578b013ad33","components/navigation/Steps.jsx":"85cb20bd45da","components/navigation/Tabs.jsx":"5d5921da1644","components/navigation/Toolbar.jsx":"ba1e0d0578b3","components/overlays/AlertDialog.jsx":"dcfbb7f61506","components/overlays/ContextMenu.jsx":"e7e3386d89ac","components/overlays/Drawer.jsx":"a1c719da3f62","components/overlays/HoverCard.jsx":"5cfabde80960","components/overlays/OverlayManager.jsx":"6b58c4dad9da","components/overlays/Popconfirm.jsx":"55f08dba5f38","components/overlays/Popover.jsx":"1582f7fa5533","components/overlays/Tour.jsx":"707cd7464f0c","components/textfield/TextField.jsx":"c06bd9729f20","image-slot.js":"26886a229370","tokens/tokens.js":"ed883dc757ae","ui_kits/status-hub/StatusHub.jsx":"8674a9fcf8fc","ui_kits/status-hub/data.js":"664bbbb30cb3","ui_kits/website/Website.jsx":"c6a98330480b","ui_kits/website/copy.js":"9d42c52c17cb"},"inlinedExternals":[],"unexposedExports":[{"name":"attachFocusTrap","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"cx","sourcePath":"components/_utils/cx.js"},{"name":"focusableSelector","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"formatCurrency","sourcePath":"components/_i18n/i18n.js"},{"name":"formatDate","sourcePath":"components/_i18n/i18n.js"},{"name":"formatNumber","sourcePath":"components/_i18n/i18n.js"},{"name":"getOverlayManager","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"getPath","sourcePath":"components/forms/Form.jsx"},{"name":"makeT","sourcePath":"components/_i18n/i18n.js"},{"name":"monthName","sourcePath":"components/_i18n/i18n.js"},{"name":"qrMatrix","sourcePath":"components/data/qr-encode.js"},{"name":"resolveLang","sourcePath":"components/_i18n/i18n.js"},{"name":"setPath","sourcePath":"components/forms/Form.jsx"},{"name":"strings","sourcePath":"components/_i18n/strings.js"},{"name":"tokens","sourcePath":"tokens/tokens.js"},{"name":"tr","sourcePath":"components/_i18n/i18n.js"},{"name":"useLang","sourcePath":"components/_i18n/i18n.js"},{"name":"useOverlayLayer","sourcePath":"components/overlays/OverlayManager.jsx"}]} */
|
|
2
2
|
|
|
3
3
|
(() => {
|
|
4
4
|
|
|
@@ -80,8 +80,8 @@ const strings = {
|
|
|
80
80
|
vi: { input: "Ô nhập lệnh" }
|
|
81
81
|
},
|
|
82
82
|
DataGrid: {
|
|
83
|
-
en: { empty: "No records", selectAll: "Select all rows", selectRow: "Select row" },
|
|
84
|
-
vi: { empty: "Không có bản ghi", selectAll: "Chọn tất cả", selectRow: "Chọn dòng" }
|
|
83
|
+
en: { empty: "No records", selectAll: "Select all rows", selectRow: "Select row", pin: "Pin this column", pinNamed: "Pin column {name}" },
|
|
84
|
+
vi: { empty: "Không có bản ghi", selectAll: "Chọn tất cả", selectRow: "Chọn dòng", pin: "Ghim cột này", pinNamed: "Ghim cột {name}" }
|
|
85
85
|
},
|
|
86
86
|
Splitter: {
|
|
87
87
|
en: { label: "Resize panes" },
|
|
@@ -190,6 +190,54 @@ const strings = {
|
|
|
190
190
|
HumanReviewGate: {
|
|
191
191
|
en: { aria: "Human review gate", risk: "review required", approve: "Approve", reject: "Reject", reviewer: "Reviewer" },
|
|
192
192
|
vi: { aria: "Cổng kiểm duyệt của con người", risk: "cần xem xét", approve: "Phê duyệt", reject: "Từ chối", reviewer: "Người duyệt" }
|
|
193
|
+
},
|
|
194
|
+
Switch: {
|
|
195
|
+
en: { on: "On", off: "Off" },
|
|
196
|
+
vi: { on: "Bật", off: "Tắt" }
|
|
197
|
+
},
|
|
198
|
+
Tabs: {
|
|
199
|
+
en: { list: "Tabs" },
|
|
200
|
+
vi: { list: "Tab" }
|
|
201
|
+
},
|
|
202
|
+
EmptyState: {
|
|
203
|
+
en: { title: "Nothing here yet", action: "Get started" },
|
|
204
|
+
vi: { title: "Chưa có gì ở đây", action: "Bắt đầu" }
|
|
205
|
+
},
|
|
206
|
+
Alert: {
|
|
207
|
+
en: { dismiss: "Dismiss" },
|
|
208
|
+
vi: { dismiss: "Đóng" }
|
|
209
|
+
},
|
|
210
|
+
Select: {
|
|
211
|
+
en: { placeholder: "Select…" },
|
|
212
|
+
vi: { placeholder: "Chọn…" }
|
|
213
|
+
},
|
|
214
|
+
Slider: {
|
|
215
|
+
en: { label: "Slider" },
|
|
216
|
+
vi: { label: "Thanh trượt" }
|
|
217
|
+
},
|
|
218
|
+
Steps: {
|
|
219
|
+
en: { label: "Steps" },
|
|
220
|
+
vi: { label: "Các bước" }
|
|
221
|
+
},
|
|
222
|
+
Toggle: {
|
|
223
|
+
en: { pressed: "Pressed", unpressed: "Not pressed" },
|
|
224
|
+
vi: { pressed: "Đang bật", unpressed: "Chưa bật" }
|
|
225
|
+
},
|
|
226
|
+
Menu: {
|
|
227
|
+
en: { menu: "Menu" },
|
|
228
|
+
vi: { menu: "Trình đơn" }
|
|
229
|
+
},
|
|
230
|
+
ContextMenu: {
|
|
231
|
+
en: { menu: "Context menu" },
|
|
232
|
+
vi: { menu: "Trình đơn ngữ cảnh" }
|
|
233
|
+
},
|
|
234
|
+
Tooltip: {
|
|
235
|
+
en: { label: "Tooltip" },
|
|
236
|
+
vi: { label: "Chú thích" }
|
|
237
|
+
},
|
|
238
|
+
ProgressBar: {
|
|
239
|
+
en: { label: "Progress" },
|
|
240
|
+
vi: { label: "Tiến độ" }
|
|
193
241
|
}
|
|
194
242
|
};
|
|
195
243
|
Object.assign(__ds_scope, { strings });
|
|
@@ -222,7 +270,16 @@ function useLang(propLang) {
|
|
|
222
270
|
const ref = React.useRef(null);
|
|
223
271
|
const [lang, setLang] = React.useState(() => resolveLang(propLang, null));
|
|
224
272
|
React.useLayoutEffect(() => {
|
|
225
|
-
|
|
273
|
+
const el = ref.current;
|
|
274
|
+
setLang(resolveLang(propLang, el));
|
|
275
|
+
if (!el || propLang) return void 0;
|
|
276
|
+
const obs = new MutationObserver(() => setLang(resolveLang(propLang, el)));
|
|
277
|
+
let node = el.parentElement;
|
|
278
|
+
while (node) {
|
|
279
|
+
obs.observe(node, { attributes: true, attributeFilter: ["lang"] });
|
|
280
|
+
node = node.parentElement;
|
|
281
|
+
}
|
|
282
|
+
return () => obs.disconnect();
|
|
226
283
|
}, [propLang]);
|
|
227
284
|
return [ref, lang];
|
|
228
285
|
}
|
|
@@ -319,19 +376,21 @@ const TONE = {
|
|
|
319
376
|
};
|
|
320
377
|
function ConfidenceMeter({ value, level, segments = 5, label, lang, className }) {
|
|
321
378
|
let tone, filled;
|
|
379
|
+
const segs = Math.max(1, Number(segments) || 5);
|
|
322
380
|
if (value != null) {
|
|
323
|
-
|
|
324
|
-
|
|
381
|
+
const v = Math.max(0, Math.min(1, Number(value) || 0));
|
|
382
|
+
tone = v < 0.4 ? "low" : v < 0.75 ? "medium" : "high";
|
|
383
|
+
filled = Math.max(0, Math.min(segs, Math.round(v * segs)));
|
|
325
384
|
} else {
|
|
326
|
-
tone = level
|
|
327
|
-
filled = Math.round(TONE[tone].fill / 5 *
|
|
385
|
+
tone = TONE[level] ? level : "medium";
|
|
386
|
+
filled = Math.max(0, Math.min(segs, Math.round(TONE[tone].fill / 5 * segs)));
|
|
328
387
|
}
|
|
329
388
|
const meta = TONE[tone];
|
|
330
389
|
const [ref, L] = useLang(lang);
|
|
331
390
|
const t = makeT("ConfidenceMeter", L);
|
|
332
391
|
const lbl = label != null ? label : t("label");
|
|
333
392
|
const levelText = t(tone);
|
|
334
|
-
return /* @__PURE__ */ React.createElement("div", { ref, className: cx("cs-confidence", className) }, /* @__PURE__ */ React.createElement("div", { className: "cs-confidence__head" }, /* @__PURE__ */ React.createElement("span", null, lbl), /* @__PURE__ */ React.createElement("span", { className: "cs-confidence__level", style: { color: meta.color } }, levelText)), /* @__PURE__ */ React.createElement("div", { className: "cs-confidence__track", role: "meter", "aria-valuemin": 0, "aria-valuemax":
|
|
393
|
+
return /* @__PURE__ */ React.createElement("div", { ref, className: cx("cs-confidence", className) }, /* @__PURE__ */ React.createElement("div", { className: "cs-confidence__head" }, /* @__PURE__ */ React.createElement("span", null, lbl), /* @__PURE__ */ React.createElement("span", { className: "cs-confidence__level", style: { color: meta.color } }, levelText)), /* @__PURE__ */ React.createElement("div", { className: "cs-confidence__track", role: "meter", "aria-valuemin": 0, "aria-valuemax": segs, "aria-valuenow": filled, "aria-label": lbl + ": " + levelText }, Array.from({ length: segs }).map((_, i) => /* @__PURE__ */ React.createElement("span", { key: i, className: "cs-confidence__seg", style: i < filled ? { background: meta.color } : void 0 }))));
|
|
335
394
|
}
|
|
336
395
|
Object.assign(__ds_scope, { ConfidenceMeter });
|
|
337
396
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/ai/ConfidenceMeter.jsx", error: String((e && e.message) || e) }); }
|
|
@@ -988,10 +1047,17 @@ Object.assign(__ds_scope, { Tree });
|
|
|
988
1047
|
try { (() => {
|
|
989
1048
|
const { cx } = __ds_scope;
|
|
990
1049
|
function Watermark({ text = "CyberSkill", opacity = 0.09, gap = 140, rotate = -22, children, className }) {
|
|
1050
|
+
const host = React.useRef(null);
|
|
1051
|
+
const [fill, setFill] = React.useState("#45210E");
|
|
1052
|
+
React.useLayoutEffect(() => {
|
|
1053
|
+
if (!host.current || typeof getComputedStyle === "undefined") return;
|
|
1054
|
+
const c = getComputedStyle(host.current).getPropertyValue("--cs-color-text-primary").trim();
|
|
1055
|
+
if (c) setFill(c);
|
|
1056
|
+
}, []);
|
|
991
1057
|
const svg = encodeURIComponent(
|
|
992
|
-
`<svg xmlns="http://www.w3.org/2000/svg" width="${gap}" height="${gap}"><text x="50%" y="50%" font-family="Be Vietnam Pro, sans-serif" font-size="14" font-weight="700" fill="
|
|
1058
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${gap}" height="${gap}"><text x="50%" y="50%" font-family="Be Vietnam Pro, sans-serif" font-size="14" font-weight="700" fill="${fill}" fill-opacity="${opacity}" text-anchor="middle" transform="rotate(${rotate} ${gap / 2} ${gap / 2})">${String(text).replace(/&/g, "&").replace(/</g, "<")}</text></svg>`
|
|
993
1059
|
);
|
|
994
|
-
return /* @__PURE__ */ React.createElement("div", { className: cx("cs-watermark", className), style: { position: "relative" } }, children, /* @__PURE__ */ React.createElement("div", { "aria-hidden": "true", style: { position: "absolute", inset: 0, pointerEvents: "none", backgroundImage: `url("data:image/svg+xml,${svg}")` } }));
|
|
1060
|
+
return /* @__PURE__ */ React.createElement("div", { ref: host, className: cx("cs-watermark", className), style: { position: "relative" } }, children, /* @__PURE__ */ React.createElement("div", { "aria-hidden": "true", style: { position: "absolute", inset: 0, pointerEvents: "none", backgroundImage: `url("data:image/svg+xml,${svg}")` } }));
|
|
995
1061
|
}
|
|
996
1062
|
Object.assign(__ds_scope, { Watermark });
|
|
997
1063
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/data/Watermark.jsx", error: String((e && e.message) || e) }); }
|
|
@@ -1131,124 +1197,6 @@ function QRCode({ value = "", size = 128, color = "var(--cs-color-text-primary)"
|
|
|
1131
1197
|
Object.assign(__ds_scope, { QRCode });
|
|
1132
1198
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/data/QRCode.jsx", error: String((e && e.message) || e) }); }
|
|
1133
1199
|
|
|
1134
|
-
// components/datatable/DataGrid.jsx
|
|
1135
|
-
try { (() => {
|
|
1136
|
-
const { makeT, useLang } = __ds_scope;
|
|
1137
|
-
const { cx } = __ds_scope;
|
|
1138
|
-
function DataGrid({
|
|
1139
|
-
columns = [],
|
|
1140
|
-
rows = [],
|
|
1141
|
-
rowKey = "id",
|
|
1142
|
-
selectable = false,
|
|
1143
|
-
selected = [],
|
|
1144
|
-
onSelect,
|
|
1145
|
-
height = 280,
|
|
1146
|
-
caption,
|
|
1147
|
-
empty,
|
|
1148
|
-
lang,
|
|
1149
|
-
className,
|
|
1150
|
-
filterText,
|
|
1151
|
-
filterKeys,
|
|
1152
|
-
/** When true (or rows exceed virtualThreshold), only paint a window of rows. */
|
|
1153
|
-
virtual = false,
|
|
1154
|
-
/** Row threshold that auto-enables virtualization. Default 80. */
|
|
1155
|
-
virtualThreshold = 80,
|
|
1156
|
-
/** Approximate row height for windowing. Default 36. */
|
|
1157
|
-
rowHeight = 36,
|
|
1158
|
-
/** localStorage key — when set, column key order is persisted across reloads. */
|
|
1159
|
-
persistKey
|
|
1160
|
-
}) {
|
|
1161
|
-
const [sort, setSort] = React.useState(null);
|
|
1162
|
-
const [scrollTop, setScrollTop] = React.useState(0);
|
|
1163
|
-
const [colOrder, setColOrder] = React.useState(() => {
|
|
1164
|
-
if (!persistKey) return null;
|
|
1165
|
-
try {
|
|
1166
|
-
const raw = localStorage.getItem("cs:datagrid:cols:" + persistKey);
|
|
1167
|
-
const arr = raw ? JSON.parse(raw) : null;
|
|
1168
|
-
return Array.isArray(arr) ? arr : null;
|
|
1169
|
-
} catch (e) {
|
|
1170
|
-
return null;
|
|
1171
|
-
}
|
|
1172
|
-
});
|
|
1173
|
-
const [ref, L] = useLang(lang);
|
|
1174
|
-
const t = makeT("DataGrid", L);
|
|
1175
|
-
const orderedColumns = React.useMemo(() => {
|
|
1176
|
-
if (!colOrder || !colOrder.length) return columns;
|
|
1177
|
-
const map = new Map(columns.map((c) => [c.key, c]));
|
|
1178
|
-
const out = [];
|
|
1179
|
-
for (const k of colOrder) if (map.has(k)) {
|
|
1180
|
-
out.push(map.get(k));
|
|
1181
|
-
map.delete(k);
|
|
1182
|
-
}
|
|
1183
|
-
for (const c of map.values()) out.push(c);
|
|
1184
|
-
return out;
|
|
1185
|
-
}, [columns, colOrder]);
|
|
1186
|
-
const filtered = React.useMemo(() => {
|
|
1187
|
-
const q = (filterText == null ? "" : String(filterText)).trim().toLowerCase();
|
|
1188
|
-
if (!q) return rows;
|
|
1189
|
-
const keys = filterKeys && filterKeys.length ? filterKeys : orderedColumns.map((c) => c.key);
|
|
1190
|
-
return rows.filter((r) => keys.some((k) => String(r[k] == null ? "" : r[k]).toLowerCase().includes(q)));
|
|
1191
|
-
}, [rows, filterText, filterKeys, orderedColumns]);
|
|
1192
|
-
const sorted = React.useMemo(() => {
|
|
1193
|
-
if (!sort) return filtered;
|
|
1194
|
-
const col = orderedColumns.find((c) => c.key === sort.key);
|
|
1195
|
-
const val = (r) => col && col.sortValue ? col.sortValue(r) : r[sort.key];
|
|
1196
|
-
return [...filtered].sort((a, b) => {
|
|
1197
|
-
const x = val(a), y = val(b);
|
|
1198
|
-
return (x > y ? 1 : x < y ? -1 : 0) * (sort.dir === "asc" ? 1 : -1);
|
|
1199
|
-
});
|
|
1200
|
-
}, [filtered, sort, orderedColumns]);
|
|
1201
|
-
const useVirtual = virtual || sorted.length >= virtualThreshold;
|
|
1202
|
-
const bodyH = Math.max(0, height - 40);
|
|
1203
|
-
const start = useVirtual ? Math.max(0, Math.floor(scrollTop / rowHeight) - 4) : 0;
|
|
1204
|
-
const visibleCount = useVirtual ? Math.ceil(bodyH / rowHeight) + 8 : sorted.length;
|
|
1205
|
-
const end = useVirtual ? Math.min(sorted.length, start + visibleCount) : sorted.length;
|
|
1206
|
-
const slice = sorted.slice(start, end);
|
|
1207
|
-
const padTop = useVirtual ? start * rowHeight : 0;
|
|
1208
|
-
const padBottom = useVirtual ? Math.max(0, (sorted.length - end) * rowHeight) : 0;
|
|
1209
|
-
const allSel = selectable && filtered.length && filtered.every((r) => selected.includes(r[rowKey]));
|
|
1210
|
-
const toggleAll = () => onSelect && onSelect(allSel ? [] : filtered.map((r) => r[rowKey]));
|
|
1211
|
-
const toggle = (k) => onSelect && onSelect(selected.includes(k) ? selected.filter((x) => x !== k) : [...selected, k]);
|
|
1212
|
-
const pinColumn = (key) => {
|
|
1213
|
-
if (!persistKey) return;
|
|
1214
|
-
const keys = orderedColumns.map((c) => c.key);
|
|
1215
|
-
const next = [key, ...keys.filter((k) => k !== key)];
|
|
1216
|
-
setColOrder(next);
|
|
1217
|
-
try {
|
|
1218
|
-
localStorage.setItem("cs:datagrid:cols:" + persistKey, JSON.stringify(next));
|
|
1219
|
-
} catch (e) {
|
|
1220
|
-
}
|
|
1221
|
-
};
|
|
1222
|
-
return /* @__PURE__ */ React.createElement(
|
|
1223
|
-
"div",
|
|
1224
|
-
{
|
|
1225
|
-
ref,
|
|
1226
|
-
className: cx("cs-datagrid", useVirtual && "cs-datagrid--virtual", className),
|
|
1227
|
-
style: { maxBlockSize: height, overflow: "auto" },
|
|
1228
|
-
onScroll: useVirtual ? (e) => setScrollTop(e.currentTarget.scrollTop) : void 0,
|
|
1229
|
-
"data-virtual": useVirtual ? "true" : "false",
|
|
1230
|
-
"data-row-count": sorted.length
|
|
1231
|
-
},
|
|
1232
|
-
/* @__PURE__ */ React.createElement("table", { className: "cs-table" }, caption ? /* @__PURE__ */ React.createElement("caption", null, caption) : null, /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement("tr", null, selectable ? /* @__PURE__ */ React.createElement("th", { scope: "col", className: "cs-datagrid__selcol" }, /* @__PURE__ */ React.createElement("input", { type: "checkbox", "aria-label": t("selectAll"), checked: !!allSel, onChange: toggleAll })) : null, orderedColumns.map((c) => /* @__PURE__ */ React.createElement(
|
|
1233
|
-
"th",
|
|
1234
|
-
{
|
|
1235
|
-
key: c.key,
|
|
1236
|
-
scope: "col",
|
|
1237
|
-
className: c.pinned ? "cs-datagrid__pinned" : void 0,
|
|
1238
|
-
style: c.pinned ? { position: "sticky", insetInlineStart: 0, zIndex: 1, background: "var(--cs-color-surface-panel)" } : void 0,
|
|
1239
|
-
"aria-sort": sort && sort.key === c.key ? sort.dir === "asc" ? "ascending" : "descending" : void 0
|
|
1240
|
-
},
|
|
1241
|
-
c.sortable ? /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-datagrid__sort", onClick: () => setSort((s) => !s || s.key !== c.key ? { key: c.key, dir: "asc" } : s.dir === "asc" ? { key: c.key, dir: "desc" } : null) }, c.header, /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true" }, sort && sort.key === c.key ? sort.dir === "asc" ? " ▲" : " ▼" : " ↕")) : c.header,
|
|
1242
|
-
persistKey ? /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-datagrid__pin", title: "Pin column first", onClick: () => pinColumn(c.key), "aria-label": "Pin " + c.key }, "⟂") : null
|
|
1243
|
-
)))), /* @__PURE__ */ React.createElement("tbody", null, sorted.length === 0 ? /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("td", { colSpan: orderedColumns.length + (selectable ? 1 : 0), className: "cs-table__empty" }, empty != null ? empty : t("empty"))) : /* @__PURE__ */ React.createElement(React.Fragment, null, padTop > 0 ? /* @__PURE__ */ React.createElement("tr", { "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("td", { colSpan: orderedColumns.length + (selectable ? 1 : 0), style: { height: padTop, padding: 0, border: 0 } })) : null, slice.map((r, i) => {
|
|
1244
|
-
const k = r[rowKey] != null ? r[rowKey] : start + i;
|
|
1245
|
-
return /* @__PURE__ */ React.createElement("tr", { key: k, className: selected.includes(k) ? "is-selected" : void 0, style: useVirtual ? { height: rowHeight } : void 0 }, selectable ? /* @__PURE__ */ React.createElement("td", { className: "cs-datagrid__selcol" }, /* @__PURE__ */ React.createElement("input", { type: "checkbox", "aria-label": t("selectRow"), checked: selected.includes(k), onChange: () => toggle(k) })) : null, orderedColumns.map((c) => /* @__PURE__ */ React.createElement("td", { key: c.key, className: c.pinned ? "cs-datagrid__pinned" : void 0, style: c.pinned ? { position: "sticky", insetInlineStart: 0, background: "var(--cs-color-surface-panel)" } : void 0 }, c.render ? c.render(r) : r[c.key])));
|
|
1246
|
-
}), padBottom > 0 ? /* @__PURE__ */ React.createElement("tr", { "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("td", { colSpan: orderedColumns.length + (selectable ? 1 : 0), style: { height: padBottom, padding: 0, border: 0 } })) : null)))
|
|
1247
|
-
);
|
|
1248
|
-
}
|
|
1249
|
-
Object.assign(__ds_scope, { DataGrid });
|
|
1250
|
-
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/datatable/DataGrid.jsx", error: String((e && e.message) || e) }); }
|
|
1251
|
-
|
|
1252
1200
|
// components/datatable/DataTable.jsx
|
|
1253
1201
|
try { (() => {
|
|
1254
1202
|
const { makeT, useLang } = __ds_scope;
|
|
@@ -1328,15 +1276,17 @@ Object.assign(__ds_scope, { EmptyState });
|
|
|
1328
1276
|
try { (() => {
|
|
1329
1277
|
const { cx } = __ds_scope;
|
|
1330
1278
|
function ProgressBar({ value = 0, max = 100, variant, label, className }) {
|
|
1331
|
-
const
|
|
1279
|
+
const safeMax = max > 0 ? max : 100;
|
|
1280
|
+
const clamped = Math.max(0, Math.min(safeMax, Number(value) || 0));
|
|
1281
|
+
const pct = Math.max(0, Math.min(100, clamped / safeMax * 100));
|
|
1332
1282
|
return /* @__PURE__ */ React.createElement(
|
|
1333
1283
|
"div",
|
|
1334
1284
|
{
|
|
1335
1285
|
className: cx("cs-progress", variant && `cs-progress--${variant}`, className),
|
|
1336
1286
|
role: "progressbar",
|
|
1337
|
-
"aria-valuenow": Math.round(
|
|
1287
|
+
"aria-valuenow": Math.round(clamped),
|
|
1338
1288
|
"aria-valuemin": 0,
|
|
1339
|
-
"aria-valuemax":
|
|
1289
|
+
"aria-valuemax": safeMax,
|
|
1340
1290
|
"aria-label": label
|
|
1341
1291
|
},
|
|
1342
1292
|
/* @__PURE__ */ React.createElement("span", { className: "cs-progress__fill", style: { inlineSize: pct + "%", width: pct + "%" } })
|
|
@@ -1492,7 +1442,42 @@ function Cascader({ nodes = [], value = [], onChange, placeholder, label, disabl
|
|
|
1492
1442
|
if (wrap.current && !wrap.current.contains(e.target)) setOpen(false);
|
|
1493
1443
|
};
|
|
1494
1444
|
const k = (e) => {
|
|
1495
|
-
if (e.key === "Escape")
|
|
1445
|
+
if (e.key === "Escape") {
|
|
1446
|
+
setOpen(false);
|
|
1447
|
+
const field = wrap.current && wrap.current.querySelector(".cs-treeselect__field");
|
|
1448
|
+
field && field.focus && field.focus();
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
if (!wrap.current) return;
|
|
1452
|
+
const opts = [...wrap.current.querySelectorAll('[role="option"]')];
|
|
1453
|
+
if (!opts.length) return;
|
|
1454
|
+
const active = document.activeElement;
|
|
1455
|
+
const idx = opts.indexOf(active);
|
|
1456
|
+
if (e.key === "ArrowDown") {
|
|
1457
|
+
e.preventDefault();
|
|
1458
|
+
(opts[idx < 0 ? 0 : Math.min(opts.length - 1, idx + 1)] || opts[0]).focus();
|
|
1459
|
+
} else if (e.key === "ArrowUp") {
|
|
1460
|
+
e.preventDefault();
|
|
1461
|
+
(opts[idx < 0 ? opts.length - 1 : Math.max(0, idx - 1)] || opts[0]).focus();
|
|
1462
|
+
} else if (e.key === "Home") {
|
|
1463
|
+
e.preventDefault();
|
|
1464
|
+
opts[0].focus();
|
|
1465
|
+
} else if (e.key === "End") {
|
|
1466
|
+
e.preventDefault();
|
|
1467
|
+
opts[opts.length - 1].focus();
|
|
1468
|
+
} else if (e.key === "ArrowRight" && idx >= 0) {
|
|
1469
|
+
active.click && active.click();
|
|
1470
|
+
} else if (e.key === "ArrowLeft") {
|
|
1471
|
+
e.preventDefault();
|
|
1472
|
+
if (path.length) {
|
|
1473
|
+
const next = path.slice(0, -1);
|
|
1474
|
+
setPath(next);
|
|
1475
|
+
} else {
|
|
1476
|
+
setOpen(false);
|
|
1477
|
+
const field = wrap.current.querySelector(".cs-treeselect__field");
|
|
1478
|
+
field && field.focus && field.focus();
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1496
1481
|
};
|
|
1497
1482
|
document.addEventListener("mousedown", d);
|
|
1498
1483
|
document.addEventListener("keydown", k);
|
|
@@ -1500,7 +1485,7 @@ function Cascader({ nodes = [], value = [], onChange, placeholder, label, disabl
|
|
|
1500
1485
|
document.removeEventListener("mousedown", d);
|
|
1501
1486
|
document.removeEventListener("keydown", k);
|
|
1502
1487
|
};
|
|
1503
|
-
}, [open]);
|
|
1488
|
+
}, [open, path]);
|
|
1504
1489
|
const cols = [];
|
|
1505
1490
|
let level = nodes;
|
|
1506
1491
|
for (let i = 0; level && level.length; i++) {
|
|
@@ -1521,7 +1506,27 @@ function Cascader({ nodes = [], value = [], onChange, placeholder, label, disabl
|
|
|
1521
1506
|
return /* @__PURE__ */ React.createElement("div", { ref: (el) => {
|
|
1522
1507
|
wrap.current = el;
|
|
1523
1508
|
ref.current = el;
|
|
1524
|
-
}, className: cx("cs-cascader", className) }, /* @__PURE__ */ React.createElement(
|
|
1509
|
+
}, className: cx("cs-cascader", className) }, /* @__PURE__ */ React.createElement(
|
|
1510
|
+
"button",
|
|
1511
|
+
{
|
|
1512
|
+
type: "button",
|
|
1513
|
+
id: fieldId,
|
|
1514
|
+
className: "cs-treeselect__field",
|
|
1515
|
+
disabled,
|
|
1516
|
+
"aria-haspopup": "listbox",
|
|
1517
|
+
"aria-expanded": open,
|
|
1518
|
+
"aria-label": label,
|
|
1519
|
+
onClick: () => setOpen((o) => !o),
|
|
1520
|
+
onKeyDown: (e) => {
|
|
1521
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
1522
|
+
e.preventDefault();
|
|
1523
|
+
setOpen(true);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
},
|
|
1527
|
+
/* @__PURE__ */ React.createElement("span", { className: labels.length ? void 0 : "ph" }, labels.length ? labels.join(" / ") : ph),
|
|
1528
|
+
/* @__PURE__ */ React.createElement("span", { "aria-hidden": "true" }, "▾")
|
|
1529
|
+
), open ? /* @__PURE__ */ React.createElement("div", { className: "cs-cascader__pop" }, cols.map((col, i) => /* @__PURE__ */ React.createElement("ul", { key: i, role: "listbox", "aria-labelledby": fieldId, className: "cs-cascader__col" }, col.map((n) => (
|
|
1525
1530
|
// role="none" — the <li> wrapper must not sit between listbox and option.
|
|
1526
1531
|
/* @__PURE__ */ React.createElement("li", { key: n.key, role: "none" }, /* @__PURE__ */ React.createElement(
|
|
1527
1532
|
"button",
|
|
@@ -1530,6 +1535,7 @@ function Cascader({ nodes = [], value = [], onChange, placeholder, label, disabl
|
|
|
1530
1535
|
role: "option",
|
|
1531
1536
|
"aria-selected": path[i] === n.key,
|
|
1532
1537
|
className: cx("cs-cascader__opt", path[i] === n.key && "on"),
|
|
1538
|
+
"data-cs-focusable": "",
|
|
1533
1539
|
onClick: () => {
|
|
1534
1540
|
const next = [...path.slice(0, i), n.key];
|
|
1535
1541
|
setPath(next);
|
|
@@ -1759,8 +1765,24 @@ Object.assign(__ds_scope, { DatePicker });
|
|
|
1759
1765
|
try { (() => {
|
|
1760
1766
|
const { makeT, useLang } = __ds_scope;
|
|
1761
1767
|
const { cx } = __ds_scope;
|
|
1768
|
+
function sanitizeHtml(html) {
|
|
1769
|
+
if (html == null || html === "") return "";
|
|
1770
|
+
if (typeof document === "undefined") {
|
|
1771
|
+
return String(html).replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "").replace(/on\w+\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, "").replace(/javascript:/gi, "");
|
|
1772
|
+
}
|
|
1773
|
+
const tpl = document.createElement("template");
|
|
1774
|
+
tpl.innerHTML = String(html);
|
|
1775
|
+
tpl.content.querySelectorAll("script,style,iframe,object,embed,link").forEach((n) => n.remove());
|
|
1776
|
+
tpl.content.querySelectorAll("*").forEach((n) => {
|
|
1777
|
+
[...n.attributes].forEach((a) => {
|
|
1778
|
+
if (/^on/i.test(a.name) || /javascript:/i.test(a.value)) n.removeAttribute(a.name);
|
|
1779
|
+
});
|
|
1780
|
+
});
|
|
1781
|
+
return tpl.innerHTML;
|
|
1782
|
+
}
|
|
1762
1783
|
function Editor({ defaultValue = "", onChange, minHeight = 120, lang, className }) {
|
|
1763
1784
|
const box = React.useRef(null);
|
|
1785
|
+
const seeded = React.useRef(false);
|
|
1764
1786
|
const [ref, L] = useLang(lang);
|
|
1765
1787
|
const t = makeT("Editor", L);
|
|
1766
1788
|
const cmd = (c) => {
|
|
@@ -1771,6 +1793,11 @@ function Editor({ defaultValue = "", onChange, minHeight = 120, lang, className
|
|
|
1771
1793
|
const emit = () => {
|
|
1772
1794
|
onChange && box.current && onChange(box.current.innerHTML);
|
|
1773
1795
|
};
|
|
1796
|
+
React.useLayoutEffect(() => {
|
|
1797
|
+
if (!box.current || seeded.current) return;
|
|
1798
|
+
box.current.innerHTML = sanitizeHtml(defaultValue);
|
|
1799
|
+
seeded.current = true;
|
|
1800
|
+
}, [defaultValue]);
|
|
1774
1801
|
const B = ({ c, label, children }) => /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-toolbar__btn", "aria-label": label, onMouseDown: (e) => {
|
|
1775
1802
|
e.preventDefault();
|
|
1776
1803
|
cmd(c);
|
|
@@ -1786,8 +1813,7 @@ function Editor({ defaultValue = "", onChange, minHeight = 120, lang, className
|
|
|
1786
1813
|
"aria-multiline": "true",
|
|
1787
1814
|
"aria-label": t("area"),
|
|
1788
1815
|
style: { minHeight },
|
|
1789
|
-
onInput: emit
|
|
1790
|
-
dangerouslySetInnerHTML: { __html: defaultValue }
|
|
1816
|
+
onInput: emit
|
|
1791
1817
|
}
|
|
1792
1818
|
));
|
|
1793
1819
|
}
|
|
@@ -1800,6 +1826,7 @@ const { makeT, useLang } = __ds_scope;
|
|
|
1800
1826
|
const { cx } = __ds_scope;
|
|
1801
1827
|
function FileUpload({ title, hint, accept, multiple = false, onFiles, icon, lang, className }) {
|
|
1802
1828
|
const [drag, setDrag] = React.useState(false);
|
|
1829
|
+
const inputRef = React.useRef(null);
|
|
1803
1830
|
const pick = (files) => {
|
|
1804
1831
|
if (files && files.length && onFiles) onFiles(Array.from(files));
|
|
1805
1832
|
};
|
|
@@ -1807,8 +1834,9 @@ function FileUpload({ title, hint, accept, multiple = false, onFiles, icon, lang
|
|
|
1807
1834
|
const t = makeT("FileUpload", L);
|
|
1808
1835
|
const tt = title != null ? title : t("title");
|
|
1809
1836
|
const hh = hint != null ? hint : t("hint");
|
|
1837
|
+
const id = React.useId();
|
|
1810
1838
|
return /* @__PURE__ */ React.createElement(
|
|
1811
|
-
"
|
|
1839
|
+
"div",
|
|
1812
1840
|
{
|
|
1813
1841
|
ref,
|
|
1814
1842
|
className: cx("cs-dropzone", drag && "is-dragging", className),
|
|
@@ -1821,12 +1849,26 @@ function FileUpload({ title, hint, accept, multiple = false, onFiles, icon, lang
|
|
|
1821
1849
|
e.preventDefault();
|
|
1822
1850
|
setDrag(false);
|
|
1823
1851
|
pick(e.dataTransfer.files);
|
|
1824
|
-
}
|
|
1852
|
+
},
|
|
1853
|
+
onClick: () => inputRef.current && inputRef.current.click()
|
|
1825
1854
|
},
|
|
1826
|
-
/* @__PURE__ */ React.createElement("span", { className: "cs-dropzone__icon" }, icon ?? /* @__PURE__ */ React.createElement("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round"
|
|
1827
|
-
/* @__PURE__ */ React.createElement("
|
|
1828
|
-
/* @__PURE__ */ React.createElement("span", { className: "cs-dropzone__hint" }, hh),
|
|
1829
|
-
/* @__PURE__ */ React.createElement(
|
|
1855
|
+
/* @__PURE__ */ React.createElement("span", { className: "cs-dropzone__icon", "aria-hidden": "true" }, icon ?? /* @__PURE__ */ React.createElement("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M12 16V4M7 9l5-5 5 5" }), /* @__PURE__ */ React.createElement("path", { d: "M5 16v3a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-3" }))),
|
|
1856
|
+
/* @__PURE__ */ React.createElement("label", { className: "cs-dropzone__title", htmlFor: id }, tt),
|
|
1857
|
+
/* @__PURE__ */ React.createElement("span", { className: "cs-dropzone__hint", id: id + "-hint" }, hh),
|
|
1858
|
+
/* @__PURE__ */ React.createElement(
|
|
1859
|
+
"input",
|
|
1860
|
+
{
|
|
1861
|
+
id,
|
|
1862
|
+
ref: inputRef,
|
|
1863
|
+
type: "file",
|
|
1864
|
+
accept,
|
|
1865
|
+
multiple,
|
|
1866
|
+
className: "cs-sr-only",
|
|
1867
|
+
"aria-describedby": id + "-hint",
|
|
1868
|
+
onChange: (e) => pick(e.target.files),
|
|
1869
|
+
onClick: (e) => e.stopPropagation()
|
|
1870
|
+
}
|
|
1871
|
+
)
|
|
1830
1872
|
);
|
|
1831
1873
|
}
|
|
1832
1874
|
Object.assign(__ds_scope, { FileUpload });
|
|
@@ -2488,8 +2530,24 @@ Object.assign(__ds_scope, { Slider });
|
|
|
2488
2530
|
// components/forms/Switch.jsx
|
|
2489
2531
|
try { (() => {
|
|
2490
2532
|
const { cx } = __ds_scope;
|
|
2491
|
-
|
|
2492
|
-
|
|
2533
|
+
let warnedNameless = false;
|
|
2534
|
+
function Switch({ label, disabled = false, className, children, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...props }) {
|
|
2535
|
+
const named = !!(label || ariaLabel || ariaLabelledby);
|
|
2536
|
+
if (!named && !warnedNameless && typeof console !== "undefined" && console.warn) {
|
|
2537
|
+
warnedNameless = true;
|
|
2538
|
+
console.warn("CyberSkill Switch: render with label, aria-label, or aria-labelledby.");
|
|
2539
|
+
}
|
|
2540
|
+
return /* @__PURE__ */ React.createElement("label", { className: cx("cs-switch", disabled && "is-disabled", className) }, /* @__PURE__ */ React.createElement(
|
|
2541
|
+
"input",
|
|
2542
|
+
{
|
|
2543
|
+
type: "checkbox",
|
|
2544
|
+
role: "switch",
|
|
2545
|
+
disabled,
|
|
2546
|
+
"aria-label": ariaLabel,
|
|
2547
|
+
"aria-labelledby": ariaLabelledby,
|
|
2548
|
+
...props
|
|
2549
|
+
}
|
|
2550
|
+
), /* @__PURE__ */ React.createElement("span", { className: "cs-switch__track", "aria-hidden": "true" }), label ? /* @__PURE__ */ React.createElement("span", { className: "cs-switch__label" }, label) : null);
|
|
2493
2551
|
}
|
|
2494
2552
|
Object.assign(__ds_scope, { Switch });
|
|
2495
2553
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Switch.jsx", error: String((e && e.message) || e) }); }
|
|
@@ -2589,8 +2647,10 @@ const CLOCK = /* @__PURE__ */ React.createElement("svg", { width: "16", height:
|
|
|
2589
2647
|
function TimePicker({ value = "09:00", onChange, step = 30, label, disabled = false, lang, className }) {
|
|
2590
2648
|
const [ref, L] = useLang(lang);
|
|
2591
2649
|
const t = makeT("TimePicker", L);
|
|
2650
|
+
const stepMin = Number(step);
|
|
2651
|
+
const safeStep = Number.isFinite(stepMin) && stepMin > 0 ? stepMin : 30;
|
|
2592
2652
|
const opts = [];
|
|
2593
|
-
for (let m = 0; m < 24 * 60; m +=
|
|
2653
|
+
for (let m = 0; m < 24 * 60; m += safeStep) {
|
|
2594
2654
|
opts.push(String(Math.floor(m / 60)).padStart(2, "0") + ":" + String(m % 60).padStart(2, "0"));
|
|
2595
2655
|
}
|
|
2596
2656
|
return /* @__PURE__ */ React.createElement("span", { ref, className: cx("cs-timepicker", className) }, CLOCK, /* @__PURE__ */ React.createElement("select", { "aria-label": label != null ? label : t("label"), disabled, value, onChange: (e) => onChange && onChange(e.target.value) }, opts.map((o) => /* @__PURE__ */ React.createElement("option", { key: o, value: o }, o))));
|
|
@@ -2730,7 +2790,8 @@ const CS_ICONS = {
|
|
|
2730
2790
|
edit: { viewBox: "0 0 24 24", els: [["path", { d: "M4 20h4L18.5 9.5a2.12 2.12 0 0 0-3-3L5 17z" }], ["path", { d: "M13.5 6.5l3 3" }]] },
|
|
2731
2791
|
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" }]] },
|
|
2732
2792
|
info: { viewBox: "0 0 24 24", els: [["circle", { cx: 12, cy: 12, r: 9 }], ["path", { d: "M12 11v5M12 7.75v.01" }]] },
|
|
2733
|
-
"alert-triangle": { viewBox: "0 0 24 24", els: [["path", { d: "M12 3.5l9 16H3z" }], ["path", { d: "M12 10v4M12 17.5v.01" }]] }
|
|
2793
|
+
"alert-triangle": { viewBox: "0 0 24 24", els: [["path", { d: "M12 3.5l9 16H3z" }], ["path", { d: "M12 10v4M12 17.5v.01" }]] },
|
|
2794
|
+
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" }]] }
|
|
2734
2795
|
};
|
|
2735
2796
|
function Icon({ name, size = "md", label, className, strokeWidth = 1.75, ...props }) {
|
|
2736
2797
|
const def = CS_ICONS[name] || CS_ICONS.sparkle;
|
|
@@ -2791,102 +2852,134 @@ function Image({ src, alt = "", ratio, preview = false, fallback, lang, classNam
|
|
|
2791
2852
|
Object.assign(__ds_scope, { Image });
|
|
2792
2853
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/data/Image.jsx", error: String((e && e.message) || e) }); }
|
|
2793
2854
|
|
|
2794
|
-
// components/
|
|
2855
|
+
// components/datatable/DataGrid.jsx
|
|
2795
2856
|
try { (() => {
|
|
2796
2857
|
const { makeT, useLang } = __ds_scope;
|
|
2797
2858
|
const { Icon } = __ds_scope;
|
|
2798
2859
|
const { cx } = __ds_scope;
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
"
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
"iframe",
|
|
2810
|
-
'[contenteditable]:not([contenteditable="false"])',
|
|
2811
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
2812
|
-
].join(",");
|
|
2813
|
-
function Dialog({
|
|
2814
|
-
open,
|
|
2815
|
-
title,
|
|
2816
|
-
children,
|
|
2817
|
-
actions,
|
|
2818
|
-
onClose,
|
|
2819
|
-
className,
|
|
2820
|
-
closeLabel,
|
|
2860
|
+
function DataGrid({
|
|
2861
|
+
columns = [],
|
|
2862
|
+
rows = [],
|
|
2863
|
+
rowKey = "id",
|
|
2864
|
+
selectable = false,
|
|
2865
|
+
selected = [],
|
|
2866
|
+
onSelect,
|
|
2867
|
+
height = 280,
|
|
2868
|
+
caption,
|
|
2869
|
+
empty,
|
|
2821
2870
|
lang,
|
|
2822
|
-
|
|
2871
|
+
className,
|
|
2872
|
+
filterText,
|
|
2873
|
+
filterKeys,
|
|
2874
|
+
/** When true (or rows exceed virtualThreshold), only paint a window of rows. */
|
|
2875
|
+
virtual = false,
|
|
2876
|
+
/** Row threshold that auto-enables virtualization. Default 80. */
|
|
2877
|
+
virtualThreshold = 80,
|
|
2878
|
+
/** Approximate row height for windowing. Default 36. */
|
|
2879
|
+
rowHeight = 36,
|
|
2880
|
+
/** localStorage key — when set, column key order is persisted across reloads. */
|
|
2881
|
+
persistKey
|
|
2823
2882
|
}) {
|
|
2824
|
-
const
|
|
2825
|
-
const
|
|
2826
|
-
const
|
|
2883
|
+
const [sort, setSort] = React.useState(null);
|
|
2884
|
+
const [scrollTop, setScrollTop] = React.useState(0);
|
|
2885
|
+
const [colOrder, setColOrder] = React.useState(() => {
|
|
2886
|
+
if (!persistKey) return null;
|
|
2887
|
+
try {
|
|
2888
|
+
const raw = localStorage.getItem("cs:datagrid:cols:" + persistKey);
|
|
2889
|
+
const arr = raw ? JSON.parse(raw) : null;
|
|
2890
|
+
return Array.isArray(arr) ? arr : null;
|
|
2891
|
+
} catch (e) {
|
|
2892
|
+
return null;
|
|
2893
|
+
}
|
|
2894
|
+
});
|
|
2827
2895
|
const [ref, L] = useLang(lang);
|
|
2828
|
-
const
|
|
2829
|
-
const
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
const
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
const
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
const
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2896
|
+
const t = makeT("DataGrid", L);
|
|
2897
|
+
const orderedColumns = React.useMemo(() => {
|
|
2898
|
+
if (!colOrder || !colOrder.length) return columns;
|
|
2899
|
+
const map = new Map(columns.map((c) => [c.key, c]));
|
|
2900
|
+
const out = [];
|
|
2901
|
+
for (const k of colOrder) if (map.has(k)) {
|
|
2902
|
+
out.push(map.get(k));
|
|
2903
|
+
map.delete(k);
|
|
2904
|
+
}
|
|
2905
|
+
for (const c of map.values()) out.push(c);
|
|
2906
|
+
return out;
|
|
2907
|
+
}, [columns, colOrder]);
|
|
2908
|
+
const filtered = React.useMemo(() => {
|
|
2909
|
+
const q = (filterText == null ? "" : String(filterText)).trim().toLowerCase();
|
|
2910
|
+
if (!q) return rows;
|
|
2911
|
+
const keys = filterKeys && filterKeys.length ? filterKeys : orderedColumns.map((c) => c.key);
|
|
2912
|
+
return rows.filter((r) => keys.some((k) => String(r[k] == null ? "" : r[k]).toLowerCase().includes(q)));
|
|
2913
|
+
}, [rows, filterText, filterKeys, orderedColumns]);
|
|
2914
|
+
const sorted = React.useMemo(() => {
|
|
2915
|
+
if (!sort) return filtered;
|
|
2916
|
+
const col = orderedColumns.find((c) => c.key === sort.key);
|
|
2917
|
+
const val = (r) => col && col.sortValue ? col.sortValue(r) : r[sort.key];
|
|
2918
|
+
return [...filtered].sort((a, b) => {
|
|
2919
|
+
const x = val(a), y = val(b);
|
|
2920
|
+
return (x > y ? 1 : x < y ? -1 : 0) * (sort.dir === "asc" ? 1 : -1);
|
|
2921
|
+
});
|
|
2922
|
+
}, [filtered, sort, orderedColumns]);
|
|
2923
|
+
const useVirtual = virtual || sorted.length >= virtualThreshold;
|
|
2924
|
+
const bodyH = Math.max(0, height - 40);
|
|
2925
|
+
const start = useVirtual ? Math.max(0, Math.floor(scrollTop / rowHeight) - 4) : 0;
|
|
2926
|
+
const visibleCount = useVirtual ? Math.ceil(bodyH / rowHeight) + 8 : sorted.length;
|
|
2927
|
+
const end = useVirtual ? Math.min(sorted.length, start + visibleCount) : sorted.length;
|
|
2928
|
+
const slice = sorted.slice(start, end);
|
|
2929
|
+
const padTop = useVirtual ? start * rowHeight : 0;
|
|
2930
|
+
const padBottom = useVirtual ? Math.max(0, (sorted.length - end) * rowHeight) : 0;
|
|
2931
|
+
const allSel = selectable && filtered.length && filtered.every((r) => selected.includes(r[rowKey]));
|
|
2932
|
+
const toggleAll = () => onSelect && onSelect(allSel ? [] : filtered.map((r) => r[rowKey]));
|
|
2933
|
+
const toggle = (k) => onSelect && onSelect(selected.includes(k) ? selected.filter((x) => x !== k) : [...selected, k]);
|
|
2934
|
+
const pinColumn = (key) => {
|
|
2935
|
+
if (!persistKey) return;
|
|
2936
|
+
const keys = orderedColumns.map((c) => c.key);
|
|
2937
|
+
const next = [key, ...keys.filter((k) => k !== key)];
|
|
2938
|
+
setColOrder(next);
|
|
2939
|
+
try {
|
|
2940
|
+
localStorage.setItem("cs:datagrid:cols:" + persistKey, JSON.stringify(next));
|
|
2941
|
+
} catch (e) {
|
|
2942
|
+
}
|
|
2943
|
+
};
|
|
2944
|
+
return /* @__PURE__ */ React.createElement(
|
|
2945
|
+
"div",
|
|
2873
2946
|
{
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
"
|
|
2879
|
-
"
|
|
2880
|
-
"aria-describedby": bodyId != null ? bodyId : props["aria-describedby"],
|
|
2881
|
-
className: cx("cs-dialog", className)
|
|
2947
|
+
ref,
|
|
2948
|
+
className: cx("cs-datagrid", useVirtual && "cs-datagrid--virtual", className),
|
|
2949
|
+
style: { maxBlockSize: height, overflow: "auto" },
|
|
2950
|
+
onScroll: useVirtual ? (e) => setScrollTop(e.currentTarget.scrollTop) : void 0,
|
|
2951
|
+
"data-virtual": useVirtual ? "true" : "false",
|
|
2952
|
+
"data-row-count": sorted.length
|
|
2882
2953
|
},
|
|
2883
|
-
/* @__PURE__ */ React.createElement("
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2954
|
+
/* @__PURE__ */ React.createElement("table", { className: "cs-table" }, caption ? /* @__PURE__ */ React.createElement("caption", null, caption) : null, /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement("tr", null, selectable ? /* @__PURE__ */ React.createElement("th", { scope: "col", className: "cs-datagrid__selcol" }, /* @__PURE__ */ React.createElement("input", { type: "checkbox", "aria-label": t("selectAll"), checked: !!allSel, onChange: toggleAll })) : null, orderedColumns.map((c) => /* @__PURE__ */ React.createElement(
|
|
2955
|
+
"th",
|
|
2956
|
+
{
|
|
2957
|
+
key: c.key,
|
|
2958
|
+
scope: "col",
|
|
2959
|
+
className: c.pinned ? "cs-datagrid__pinned" : void 0,
|
|
2960
|
+
style: c.pinned ? { position: "sticky", insetInlineStart: 0, zIndex: 1, background: "var(--cs-color-surface-panel)" } : void 0,
|
|
2961
|
+
"aria-sort": sort && sort.key === c.key ? sort.dir === "asc" ? "ascending" : "descending" : void 0
|
|
2962
|
+
},
|
|
2963
|
+
c.sortable ? /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-datagrid__sort", onClick: () => setSort((s) => !s || s.key !== c.key ? { key: c.key, dir: "asc" } : s.dir === "asc" ? { key: c.key, dir: "desc" } : null) }, c.header, /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true" }, sort && sort.key === c.key ? sort.dir === "asc" ? " ▲" : " ▼" : " ↕")) : c.header,
|
|
2964
|
+
persistKey ? /* @__PURE__ */ React.createElement(
|
|
2965
|
+
"button",
|
|
2966
|
+
{
|
|
2967
|
+
type: "button",
|
|
2968
|
+
className: "cs-datagrid__pin",
|
|
2969
|
+
title: t("pin"),
|
|
2970
|
+
onClick: () => pinColumn(c.key),
|
|
2971
|
+
"aria-label": t("pinNamed").replace("{name}", String(c.header != null ? c.header : c.key))
|
|
2972
|
+
},
|
|
2973
|
+
/* @__PURE__ */ React.createElement(Icon, { name: "pin", size: "sm" })
|
|
2974
|
+
) : null
|
|
2975
|
+
)))), /* @__PURE__ */ React.createElement("tbody", null, sorted.length === 0 ? /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("td", { colSpan: orderedColumns.length + (selectable ? 1 : 0), className: "cs-table__empty" }, empty != null ? empty : t("empty"))) : /* @__PURE__ */ React.createElement(React.Fragment, null, padTop > 0 ? /* @__PURE__ */ React.createElement("tr", { "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("td", { colSpan: orderedColumns.length + (selectable ? 1 : 0), style: { height: padTop, padding: 0, border: 0 } })) : null, slice.map((r, i) => {
|
|
2976
|
+
const k = r[rowKey] != null ? r[rowKey] : start + i;
|
|
2977
|
+
return /* @__PURE__ */ React.createElement("tr", { key: k, className: selected.includes(k) ? "is-selected" : void 0, style: useVirtual ? { height: rowHeight } : void 0 }, selectable ? /* @__PURE__ */ React.createElement("td", { className: "cs-datagrid__selcol" }, /* @__PURE__ */ React.createElement("input", { type: "checkbox", "aria-label": t("selectRow"), checked: selected.includes(k), onChange: () => toggle(k) })) : null, orderedColumns.map((c) => /* @__PURE__ */ React.createElement("td", { key: c.key, className: c.pinned ? "cs-datagrid__pinned" : void 0, style: c.pinned ? { position: "sticky", insetInlineStart: 0, background: "var(--cs-color-surface-panel)" } : void 0 }, c.render ? c.render(r) : r[c.key])));
|
|
2978
|
+
}), padBottom > 0 ? /* @__PURE__ */ React.createElement("tr", { "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("td", { colSpan: orderedColumns.length + (selectable ? 1 : 0), style: { height: padBottom, padding: 0, border: 0 } })) : null)))
|
|
2979
|
+
);
|
|
2887
2980
|
}
|
|
2888
|
-
Object.assign(__ds_scope, {
|
|
2889
|
-
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/
|
|
2981
|
+
Object.assign(__ds_scope, { DataGrid });
|
|
2982
|
+
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/datatable/DataGrid.jsx", error: String((e && e.message) || e) }); }
|
|
2890
2983
|
|
|
2891
2984
|
// components/logo/logo-data.js
|
|
2892
2985
|
try { (() => {
|
|
@@ -3193,37 +3286,6 @@ function Breadcrumb({ items = [], lang, className, ...props }) {
|
|
|
3193
3286
|
Object.assign(__ds_scope, { Breadcrumb });
|
|
3194
3287
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/navigation/Breadcrumb.jsx", error: String((e && e.message) || e) }); }
|
|
3195
3288
|
|
|
3196
|
-
// components/navigation/CommandPalette.jsx
|
|
3197
|
-
try { (() => {
|
|
3198
|
-
const { makeT, useLang } = __ds_scope;
|
|
3199
|
-
const { cx } = __ds_scope;
|
|
3200
|
-
function CommandPalette({ open, onClose, placeholder, groups = [], lang, className }) {
|
|
3201
|
-
const [q, setQ] = React.useState("");
|
|
3202
|
-
React.useEffect(() => {
|
|
3203
|
-
if (!open) return;
|
|
3204
|
-
const onKey = (e) => {
|
|
3205
|
-
if (e.key === "Escape") onClose && onClose();
|
|
3206
|
-
};
|
|
3207
|
-
document.addEventListener("keydown", onKey);
|
|
3208
|
-
return () => document.removeEventListener("keydown", onKey);
|
|
3209
|
-
}, [open]);
|
|
3210
|
-
const [ref, L] = useLang(lang);
|
|
3211
|
-
const t = makeT("CommandPalette", L);
|
|
3212
|
-
const ph = placeholder != null ? placeholder : t("placeholder");
|
|
3213
|
-
if (!open) return null;
|
|
3214
|
-
const needle = q.trim().toLowerCase();
|
|
3215
|
-
return /* @__PURE__ */ React.createElement("div", { ref, className: "cs-cmdk-scrim", onClick: onClose }, /* @__PURE__ */ React.createElement("div", { className: cx("cs-cmdk", className), role: "dialog", "aria-modal": "true", "aria-label": t("aria"), onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React.createElement("div", { className: "cs-cmdk__search" }, /* @__PURE__ */ React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("circle", { cx: "11", cy: "11", r: "7" }), /* @__PURE__ */ React.createElement("path", { d: "M21 21l-4.3-4.3" })), /* @__PURE__ */ React.createElement("input", { autoFocus: true, value: q, onChange: (e) => setQ(e.target.value), placeholder: ph }), /* @__PURE__ */ React.createElement("span", { className: "cs-kbd" }, t("esc"))), /* @__PURE__ */ React.createElement("div", { className: "cs-cmdk__list" }, groups.map((g, gi) => {
|
|
3216
|
-
const items = (g.items || []).filter((it) => !needle || String(it.label).toLowerCase().includes(needle));
|
|
3217
|
-
if (!items.length) return null;
|
|
3218
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, { key: gi }, g.label ? /* @__PURE__ */ React.createElement("div", { className: "cs-cmdk__label" }, g.label) : null, items.map((it, ii) => /* @__PURE__ */ React.createElement("button", { key: ii, type: "button", className: "cs-cmdk__item", onClick: () => {
|
|
3219
|
-
it.onSelect && it.onSelect();
|
|
3220
|
-
onClose && onClose();
|
|
3221
|
-
} }, it.icon ? /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true" }, it.icon) : null, /* @__PURE__ */ React.createElement("span", null, it.label), it.shortcut ? /* @__PURE__ */ React.createElement("span", { className: "cs-kbd" }, it.shortcut) : null)));
|
|
3222
|
-
}))));
|
|
3223
|
-
}
|
|
3224
|
-
Object.assign(__ds_scope, { CommandPalette });
|
|
3225
|
-
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/navigation/CommandPalette.jsx", error: String((e && e.message) || e) }); }
|
|
3226
|
-
|
|
3227
3289
|
// components/navigation/Dock.jsx
|
|
3228
3290
|
try { (() => {
|
|
3229
3291
|
const { cx } = __ds_scope;
|
|
@@ -3567,7 +3629,8 @@ function Toolbar({ items = [], overflowAfter, label, lang, className }) {
|
|
|
3567
3629
|
const [ref, L] = useLang(lang);
|
|
3568
3630
|
const t = makeT("Toolbar", L);
|
|
3569
3631
|
const cut = overflowAfter != null ? overflowAfter : items.length;
|
|
3570
|
-
const head = items.slice(0, cut)
|
|
3632
|
+
const head = items.slice(0, cut);
|
|
3633
|
+
const tail = items.slice(cut).filter((x) => x !== "-");
|
|
3571
3634
|
React.useEffect(() => {
|
|
3572
3635
|
if (!open) return;
|
|
3573
3636
|
const d = (e) => {
|
|
@@ -3587,11 +3650,71 @@ function Toolbar({ items = [], overflowAfter, label, lang, className }) {
|
|
|
3587
3650
|
Object.assign(__ds_scope, { Toolbar });
|
|
3588
3651
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/navigation/Toolbar.jsx", error: String((e && e.message) || e) }); }
|
|
3589
3652
|
|
|
3590
|
-
// components/overlays/
|
|
3653
|
+
// components/overlays/ContextMenu.jsx
|
|
3654
|
+
try { (() => {
|
|
3655
|
+
const { cx } = __ds_scope;
|
|
3656
|
+
function ContextMenu({ items = [], children, className }) {
|
|
3657
|
+
const [pos, setPos] = React.useState(null);
|
|
3658
|
+
React.useEffect(() => {
|
|
3659
|
+
if (!pos) return;
|
|
3660
|
+
const close = () => setPos(null);
|
|
3661
|
+
const k = (e) => {
|
|
3662
|
+
if (e.key === "Escape") setPos(null);
|
|
3663
|
+
};
|
|
3664
|
+
document.addEventListener("click", close);
|
|
3665
|
+
document.addEventListener("keydown", k);
|
|
3666
|
+
return () => {
|
|
3667
|
+
document.removeEventListener("click", close);
|
|
3668
|
+
document.removeEventListener("keydown", k);
|
|
3669
|
+
};
|
|
3670
|
+
}, [pos]);
|
|
3671
|
+
return /* @__PURE__ */ React.createElement(
|
|
3672
|
+
"div",
|
|
3673
|
+
{
|
|
3674
|
+
className: cx("cs-ctxmenu-zone", className),
|
|
3675
|
+
onContextMenu: (e) => {
|
|
3676
|
+
e.preventDefault();
|
|
3677
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
3678
|
+
setPos({ x: e.clientX - r.left, y: e.clientY - r.top });
|
|
3679
|
+
}
|
|
3680
|
+
},
|
|
3681
|
+
children,
|
|
3682
|
+
pos ? /* @__PURE__ */ React.createElement("div", { className: "cs-menu__list", role: "menu", style: { position: "absolute", insetInlineStart: pos.x, insetBlockStart: pos.y } }, items.map((it, i) => it === "-" ? /* @__PURE__ */ React.createElement("div", { key: i, className: "cs-menu__sep" }) : /* @__PURE__ */ React.createElement("button", { key: i, type: "button", role: "menuitem", className: cx("cs-menu__item", it.danger && "cs-menu__item--danger"), onClick: () => {
|
|
3683
|
+
setPos(null);
|
|
3684
|
+
it.onSelect && it.onSelect();
|
|
3685
|
+
} }, it.label))) : null
|
|
3686
|
+
);
|
|
3687
|
+
}
|
|
3688
|
+
Object.assign(__ds_scope, { ContextMenu });
|
|
3689
|
+
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/overlays/ContextMenu.jsx", error: String((e && e.message) || e) }); }
|
|
3690
|
+
|
|
3691
|
+
// components/overlays/HoverCard.jsx
|
|
3591
3692
|
try { (() => {
|
|
3592
|
-
const { makeT, useLang } = __ds_scope;
|
|
3593
3693
|
const { cx } = __ds_scope;
|
|
3594
|
-
|
|
3694
|
+
function HoverCard({ trigger, children, openDelay = 150, closeDelay = 200, className }) {
|
|
3695
|
+
const [open, setOpen] = React.useState(false);
|
|
3696
|
+
const t1 = React.useRef();
|
|
3697
|
+
const t2 = React.useRef();
|
|
3698
|
+
const show = () => {
|
|
3699
|
+
clearTimeout(t2.current);
|
|
3700
|
+
t1.current = setTimeout(() => setOpen(true), openDelay);
|
|
3701
|
+
};
|
|
3702
|
+
const hide = () => {
|
|
3703
|
+
clearTimeout(t1.current);
|
|
3704
|
+
t2.current = setTimeout(() => setOpen(false), closeDelay);
|
|
3705
|
+
};
|
|
3706
|
+
React.useEffect(() => () => {
|
|
3707
|
+
clearTimeout(t1.current);
|
|
3708
|
+
clearTimeout(t2.current);
|
|
3709
|
+
}, []);
|
|
3710
|
+
return /* @__PURE__ */ React.createElement("span", { className: cx("cs-hovercard", className), onMouseEnter: show, onMouseLeave: hide, onFocus: show, onBlur: hide }, trigger, open ? /* @__PURE__ */ React.createElement("span", { className: "cs-hovercard__panel", role: "dialog" }, children) : null);
|
|
3711
|
+
}
|
|
3712
|
+
Object.assign(__ds_scope, { HoverCard });
|
|
3713
|
+
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/overlays/HoverCard.jsx", error: String((e && e.message) || e) }); }
|
|
3714
|
+
|
|
3715
|
+
// components/overlays/OverlayManager.jsx
|
|
3716
|
+
try { (() => {
|
|
3717
|
+
const focusableSelector = [
|
|
3595
3718
|
"a[href]",
|
|
3596
3719
|
"area[href]",
|
|
3597
3720
|
"button:not([disabled])",
|
|
@@ -3605,6 +3728,270 @@ const FOCUSABLE = [
|
|
|
3605
3728
|
'[contenteditable]:not([contenteditable="false"])',
|
|
3606
3729
|
'[tabindex]:not([tabindex="-1"])'
|
|
3607
3730
|
].join(",");
|
|
3731
|
+
function attachFocusTrap(panelEl, { handleEscape = false, onEscape } = {}) {
|
|
3732
|
+
if (!panelEl) return () => {
|
|
3733
|
+
};
|
|
3734
|
+
const focusables = () => [...panelEl.querySelectorAll(focusableSelector)];
|
|
3735
|
+
const k = (e) => {
|
|
3736
|
+
if (handleEscape && e.key === "Escape") {
|
|
3737
|
+
onEscape && onEscape();
|
|
3738
|
+
return;
|
|
3739
|
+
}
|
|
3740
|
+
if (e.key !== "Tab") return;
|
|
3741
|
+
const f = focusables();
|
|
3742
|
+
if (!f.length) {
|
|
3743
|
+
e.preventDefault();
|
|
3744
|
+
panelEl.focus();
|
|
3745
|
+
return;
|
|
3746
|
+
}
|
|
3747
|
+
const a = f[0];
|
|
3748
|
+
const z = f[f.length - 1];
|
|
3749
|
+
const active = document.activeElement;
|
|
3750
|
+
const inside = panelEl.contains(active);
|
|
3751
|
+
if (e.shiftKey && (!inside || active === a)) {
|
|
3752
|
+
e.preventDefault();
|
|
3753
|
+
z.focus();
|
|
3754
|
+
} else if (!e.shiftKey && (!inside || active === z)) {
|
|
3755
|
+
e.preventDefault();
|
|
3756
|
+
a.focus();
|
|
3757
|
+
}
|
|
3758
|
+
};
|
|
3759
|
+
document.addEventListener("keydown", k);
|
|
3760
|
+
return () => document.removeEventListener("keydown", k);
|
|
3761
|
+
}
|
|
3762
|
+
function createOverlayManager() {
|
|
3763
|
+
const layers = [];
|
|
3764
|
+
let prevOverflow = "";
|
|
3765
|
+
let locked = false;
|
|
3766
|
+
let escapeBound = false;
|
|
3767
|
+
const resort = () => {
|
|
3768
|
+
layers.sort((a, b) => {
|
|
3769
|
+
const pa = a.panelEl;
|
|
3770
|
+
const pb = b.panelEl;
|
|
3771
|
+
if (pa && pb && pa !== pb) {
|
|
3772
|
+
if (pa.contains(pb)) return -1;
|
|
3773
|
+
if (pb.contains(pa)) return 1;
|
|
3774
|
+
}
|
|
3775
|
+
return (a.seq || 0) - (b.seq || 0);
|
|
3776
|
+
});
|
|
3777
|
+
};
|
|
3778
|
+
const applyScroll = () => {
|
|
3779
|
+
const need = layers.some((l) => l.kind === "modal" && l.lockScroll !== false);
|
|
3780
|
+
if (need && !locked) {
|
|
3781
|
+
prevOverflow = document.body.style.overflow;
|
|
3782
|
+
document.body.style.overflow = "hidden";
|
|
3783
|
+
locked = true;
|
|
3784
|
+
} else if (!need && locked) {
|
|
3785
|
+
document.body.style.overflow = prevOverflow;
|
|
3786
|
+
locked = false;
|
|
3787
|
+
}
|
|
3788
|
+
};
|
|
3789
|
+
const onDocEscape = (e) => {
|
|
3790
|
+
if (e.key !== "Escape") return;
|
|
3791
|
+
if (!layers.length) return;
|
|
3792
|
+
resort();
|
|
3793
|
+
const top = layers[layers.length - 1];
|
|
3794
|
+
if (!top || typeof top.onEscape !== "function") return;
|
|
3795
|
+
e.preventDefault();
|
|
3796
|
+
e.stopPropagation();
|
|
3797
|
+
top.onEscape();
|
|
3798
|
+
};
|
|
3799
|
+
const ensureEscape = () => {
|
|
3800
|
+
if (escapeBound) return;
|
|
3801
|
+
escapeBound = true;
|
|
3802
|
+
document.addEventListener("keydown", onDocEscape, true);
|
|
3803
|
+
};
|
|
3804
|
+
let seq = 0;
|
|
3805
|
+
return {
|
|
3806
|
+
register(layer) {
|
|
3807
|
+
ensureEscape();
|
|
3808
|
+
const id = layer.id || `cs-ov-${++seq}`;
|
|
3809
|
+
const entry = { ...layer, id, seq: ++seq };
|
|
3810
|
+
layers.push(entry);
|
|
3811
|
+
resort();
|
|
3812
|
+
applyScroll();
|
|
3813
|
+
return () => {
|
|
3814
|
+
resort();
|
|
3815
|
+
const i = layers.findIndex((l) => l.id === id);
|
|
3816
|
+
const wasTop = i === layers.length - 1;
|
|
3817
|
+
if (i >= 0) layers.splice(i, 1);
|
|
3818
|
+
applyScroll();
|
|
3819
|
+
if (wasTop && entry.restoreEl && typeof entry.restoreEl.focus === "function") {
|
|
3820
|
+
try {
|
|
3821
|
+
entry.restoreEl.focus();
|
|
3822
|
+
} catch {
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
};
|
|
3826
|
+
},
|
|
3827
|
+
top() {
|
|
3828
|
+
resort();
|
|
3829
|
+
return layers[layers.length - 1] || null;
|
|
3830
|
+
},
|
|
3831
|
+
get scrollLocked() {
|
|
3832
|
+
return locked;
|
|
3833
|
+
},
|
|
3834
|
+
get depth() {
|
|
3835
|
+
return layers.length;
|
|
3836
|
+
}
|
|
3837
|
+
};
|
|
3838
|
+
}
|
|
3839
|
+
const defaultManager = createOverlayManager();
|
|
3840
|
+
const OverlayContext = React.createContext(null);
|
|
3841
|
+
function getOverlayManager() {
|
|
3842
|
+
return defaultManager;
|
|
3843
|
+
}
|
|
3844
|
+
function OverlayProvider({ children }) {
|
|
3845
|
+
const api = React.useMemo(() => createOverlayManager(), []);
|
|
3846
|
+
return /* @__PURE__ */ React.createElement(OverlayContext.Provider, { value: api }, /* @__PURE__ */ React.createElement("div", { id: "cs-overlay-root", "data-cs-overlay-root": "" }), children);
|
|
3847
|
+
}
|
|
3848
|
+
function useOverlayLayer({
|
|
3849
|
+
open,
|
|
3850
|
+
kind = "modal",
|
|
3851
|
+
trapFocus = false,
|
|
3852
|
+
lockScroll,
|
|
3853
|
+
onEscape,
|
|
3854
|
+
panelRef,
|
|
3855
|
+
preferFocusSelector
|
|
3856
|
+
}) {
|
|
3857
|
+
const ctx = React.useContext(OverlayContext);
|
|
3858
|
+
const mgr = ctx || defaultManager;
|
|
3859
|
+
const escapeRef = React.useRef(onEscape);
|
|
3860
|
+
escapeRef.current = onEscape;
|
|
3861
|
+
React.useLayoutEffect(() => {
|
|
3862
|
+
if (!open) return void 0;
|
|
3863
|
+
const restoreEl = typeof document !== "undefined" ? document.activeElement : null;
|
|
3864
|
+
const panel = panelRef && panelRef.current;
|
|
3865
|
+
const unregister = mgr.register({
|
|
3866
|
+
kind,
|
|
3867
|
+
lockScroll: lockScroll != null ? lockScroll : kind === "modal",
|
|
3868
|
+
onEscape: () => escapeRef.current && escapeRef.current(),
|
|
3869
|
+
restoreEl,
|
|
3870
|
+
panelEl: panel || null
|
|
3871
|
+
});
|
|
3872
|
+
let detachTrap = () => {
|
|
3873
|
+
};
|
|
3874
|
+
const top = mgr.top();
|
|
3875
|
+
const isTop = top && top.panelEl === panel;
|
|
3876
|
+
if (trapFocus && panel && isTop) {
|
|
3877
|
+
const preferred = preferFocusSelector && panel.querySelector(preferFocusSelector) || panel.querySelector(focusableSelector) || panel;
|
|
3878
|
+
preferred && preferred.focus && preferred.focus();
|
|
3879
|
+
detachTrap = attachFocusTrap(panel, { handleEscape: false });
|
|
3880
|
+
}
|
|
3881
|
+
return () => {
|
|
3882
|
+
detachTrap();
|
|
3883
|
+
unregister();
|
|
3884
|
+
};
|
|
3885
|
+
}, [open, kind, trapFocus, lockScroll, mgr, panelRef, preferFocusSelector]);
|
|
3886
|
+
return { manager: mgr };
|
|
3887
|
+
}
|
|
3888
|
+
Object.assign(__ds_scope, { focusableSelector, attachFocusTrap, getOverlayManager, OverlayProvider, useOverlayLayer });
|
|
3889
|
+
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/overlays/OverlayManager.jsx", error: String((e && e.message) || e) }); }
|
|
3890
|
+
|
|
3891
|
+
// components/dialog/Dialog.jsx
|
|
3892
|
+
try { (() => {
|
|
3893
|
+
const { makeT, useLang } = __ds_scope;
|
|
3894
|
+
const { Icon } = __ds_scope;
|
|
3895
|
+
const { cx } = __ds_scope;
|
|
3896
|
+
const { useOverlayLayer } = __ds_scope;
|
|
3897
|
+
function Dialog({
|
|
3898
|
+
open,
|
|
3899
|
+
title,
|
|
3900
|
+
children,
|
|
3901
|
+
actions,
|
|
3902
|
+
onClose,
|
|
3903
|
+
className,
|
|
3904
|
+
closeLabel,
|
|
3905
|
+
lang,
|
|
3906
|
+
...props
|
|
3907
|
+
}) {
|
|
3908
|
+
const baseId = React.useId();
|
|
3909
|
+
const titleId = baseId + "-title";
|
|
3910
|
+
const bodyId = children == null ? void 0 : baseId + "-body";
|
|
3911
|
+
const [ref, L] = useLang(lang);
|
|
3912
|
+
const panel = React.useRef(null);
|
|
3913
|
+
const closeRef = React.useRef(onClose);
|
|
3914
|
+
closeRef.current = onClose;
|
|
3915
|
+
useOverlayLayer({
|
|
3916
|
+
open: !!open,
|
|
3917
|
+
kind: "modal",
|
|
3918
|
+
trapFocus: true,
|
|
3919
|
+
onEscape: () => closeRef.current && closeRef.current(),
|
|
3920
|
+
panelRef: panel
|
|
3921
|
+
});
|
|
3922
|
+
const cl = closeLabel != null ? closeLabel : makeT("Dialog", L)("close");
|
|
3923
|
+
if (!open) return null;
|
|
3924
|
+
return /* @__PURE__ */ React.createElement("div", { ref, className: "cs-dialog-layer" }, /* @__PURE__ */ React.createElement("div", { className: "cs-dialog__overlay", onClick: onClose, "aria-hidden": "true" }), /* @__PURE__ */ React.createElement(
|
|
3925
|
+
"section",
|
|
3926
|
+
{
|
|
3927
|
+
...props,
|
|
3928
|
+
ref: panel,
|
|
3929
|
+
tabIndex: -1,
|
|
3930
|
+
role: "dialog",
|
|
3931
|
+
"aria-modal": "true",
|
|
3932
|
+
"aria-labelledby": titleId,
|
|
3933
|
+
"aria-describedby": bodyId != null ? bodyId : props["aria-describedby"],
|
|
3934
|
+
className: cx("cs-dialog", className)
|
|
3935
|
+
},
|
|
3936
|
+
/* @__PURE__ */ React.createElement("header", { className: "cs-dialog__header" }, /* @__PURE__ */ React.createElement("h2", { id: titleId, className: "cs-dialog__title" }, title), onClose ? /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-button cs-button--ghost cs-button--sm", onClick: onClose, "aria-label": cl }, /* @__PURE__ */ React.createElement(Icon, { name: "close", size: "sm" })) : null),
|
|
3937
|
+
/* @__PURE__ */ React.createElement("div", { id: bodyId, className: "cs-dialog__body" }, children),
|
|
3938
|
+
actions ? /* @__PURE__ */ React.createElement("footer", { className: "cs-dialog__actions" }, actions) : null
|
|
3939
|
+
));
|
|
3940
|
+
}
|
|
3941
|
+
Object.assign(__ds_scope, { Dialog });
|
|
3942
|
+
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/dialog/Dialog.jsx", error: String((e && e.message) || e) }); }
|
|
3943
|
+
|
|
3944
|
+
// components/navigation/CommandPalette.jsx
|
|
3945
|
+
try { (() => {
|
|
3946
|
+
const { makeT, useLang } = __ds_scope;
|
|
3947
|
+
const { cx } = __ds_scope;
|
|
3948
|
+
const { useOverlayLayer } = __ds_scope;
|
|
3949
|
+
function CommandPalette({ open, onClose, placeholder, groups = [], lang, className }) {
|
|
3950
|
+
const [q, setQ] = React.useState("");
|
|
3951
|
+
const panel = React.useRef(null);
|
|
3952
|
+
const closeRef = React.useRef(onClose);
|
|
3953
|
+
closeRef.current = onClose;
|
|
3954
|
+
useOverlayLayer({
|
|
3955
|
+
open: !!open,
|
|
3956
|
+
kind: "modal",
|
|
3957
|
+
trapFocus: true,
|
|
3958
|
+
preferFocusSelector: ".cs-cmdk__search input",
|
|
3959
|
+
onEscape: () => closeRef.current && closeRef.current(),
|
|
3960
|
+
panelRef: panel
|
|
3961
|
+
});
|
|
3962
|
+
const [ref, L] = useLang(lang);
|
|
3963
|
+
const t = makeT("CommandPalette", L);
|
|
3964
|
+
const ph = placeholder != null ? placeholder : t("placeholder");
|
|
3965
|
+
if (!open) return null;
|
|
3966
|
+
const needle = q.trim().toLowerCase();
|
|
3967
|
+
return /* @__PURE__ */ React.createElement(
|
|
3968
|
+
"div",
|
|
3969
|
+
{
|
|
3970
|
+
ref: (el) => {
|
|
3971
|
+
ref.current = el;
|
|
3972
|
+
panel.current = el;
|
|
3973
|
+
},
|
|
3974
|
+
className: "cs-cmdk-scrim",
|
|
3975
|
+
onClick: onClose
|
|
3976
|
+
},
|
|
3977
|
+
/* @__PURE__ */ React.createElement("div", { className: cx("cs-cmdk", className), role: "dialog", "aria-modal": "true", "aria-label": t("aria"), onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React.createElement("div", { className: "cs-cmdk__search" }, /* @__PURE__ */ React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("circle", { cx: "11", cy: "11", r: "7" }), /* @__PURE__ */ React.createElement("path", { d: "M21 21l-4.3-4.3" })), /* @__PURE__ */ React.createElement("input", { autoFocus: true, value: q, onChange: (e) => setQ(e.target.value), placeholder: ph }), /* @__PURE__ */ React.createElement("span", { className: "cs-kbd" }, t("esc"))), /* @__PURE__ */ React.createElement("div", { className: "cs-cmdk__list" }, groups.map((g, gi) => {
|
|
3978
|
+
const items = (g.items || []).filter((it) => !needle || String(it.label).toLowerCase().includes(needle));
|
|
3979
|
+
if (!items.length) return null;
|
|
3980
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, { key: gi }, g.label ? /* @__PURE__ */ React.createElement("div", { className: "cs-cmdk__label" }, g.label) : null, items.map((it, ii) => /* @__PURE__ */ React.createElement("button", { key: ii, type: "button", className: "cs-cmdk__item", onClick: () => {
|
|
3981
|
+
it.onSelect && it.onSelect();
|
|
3982
|
+
onClose && onClose();
|
|
3983
|
+
} }, it.icon ? /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true" }, it.icon) : null, /* @__PURE__ */ React.createElement("span", null, it.label), it.shortcut ? /* @__PURE__ */ React.createElement("span", { className: "cs-kbd" }, it.shortcut) : null)));
|
|
3984
|
+
})))
|
|
3985
|
+
);
|
|
3986
|
+
}
|
|
3987
|
+
Object.assign(__ds_scope, { CommandPalette });
|
|
3988
|
+
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/navigation/CommandPalette.jsx", error: String((e && e.message) || e) }); }
|
|
3989
|
+
|
|
3990
|
+
// components/overlays/AlertDialog.jsx
|
|
3991
|
+
try { (() => {
|
|
3992
|
+
const { makeT, useLang } = __ds_scope;
|
|
3993
|
+
const { cx } = __ds_scope;
|
|
3994
|
+
const { useOverlayLayer } = __ds_scope;
|
|
3608
3995
|
function AlertDialog({
|
|
3609
3996
|
open,
|
|
3610
3997
|
defaultOpen = false,
|
|
@@ -3640,45 +4027,19 @@ function AlertDialog({
|
|
|
3640
4027
|
confirmRef.current = onConfirm;
|
|
3641
4028
|
const cancelRef = React.useRef(onCancel);
|
|
3642
4029
|
cancelRef.current = onCancel;
|
|
3643
|
-
React.
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
(
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
}
|
|
3657
|
-
if (e.key !== "Tab" || !panel.current) return;
|
|
3658
|
-
const f = focusables();
|
|
3659
|
-
if (!f.length) {
|
|
3660
|
-
e.preventDefault();
|
|
3661
|
-
panel.current.focus();
|
|
3662
|
-
return;
|
|
3663
|
-
}
|
|
3664
|
-
const a = f[0], z = f[f.length - 1];
|
|
3665
|
-
const active = document.activeElement;
|
|
3666
|
-
const inside = panel.current.contains(active);
|
|
3667
|
-
if (e.shiftKey && (!inside || active === a)) {
|
|
3668
|
-
e.preventDefault();
|
|
3669
|
-
z.focus();
|
|
3670
|
-
} else if (!e.shiftKey && (!inside || active === z)) {
|
|
3671
|
-
e.preventDefault();
|
|
3672
|
-
a.focus();
|
|
3673
|
-
}
|
|
3674
|
-
};
|
|
3675
|
-
document.addEventListener("keydown", k);
|
|
3676
|
-
return () => {
|
|
3677
|
-
document.removeEventListener("keydown", k);
|
|
3678
|
-
document.body.style.overflow = prevOverflow;
|
|
3679
|
-
if (prev && prev.focus) prev.focus();
|
|
3680
|
-
};
|
|
3681
|
-
}, [isOpen]);
|
|
4030
|
+
const setOpenRef = React.useRef(setOpen);
|
|
4031
|
+
setOpenRef.current = setOpen;
|
|
4032
|
+
useOverlayLayer({
|
|
4033
|
+
open: isOpen,
|
|
4034
|
+
kind: "modal",
|
|
4035
|
+
trapFocus: true,
|
|
4036
|
+
preferFocusSelector: ".cs-alert-dialog__confirm",
|
|
4037
|
+
onEscape: () => {
|
|
4038
|
+
setOpenRef.current(false);
|
|
4039
|
+
cancelRef.current?.();
|
|
4040
|
+
},
|
|
4041
|
+
panelRef: panel
|
|
4042
|
+
});
|
|
3682
4043
|
const cl = cancelLabel != null ? cancelLabel : t("cancel");
|
|
3683
4044
|
const cf = confirmLabel != null ? confirmLabel : t("confirm");
|
|
3684
4045
|
const body = description ?? children;
|
|
@@ -3741,111 +4102,46 @@ function AlertDialog({
|
|
|
3741
4102
|
Object.assign(__ds_scope, { AlertDialog });
|
|
3742
4103
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/overlays/AlertDialog.jsx", error: String((e && e.message) || e) }); }
|
|
3743
4104
|
|
|
3744
|
-
// components/overlays/ContextMenu.jsx
|
|
3745
|
-
try { (() => {
|
|
3746
|
-
const { cx } = __ds_scope;
|
|
3747
|
-
function ContextMenu({ items = [], children, className }) {
|
|
3748
|
-
const [pos, setPos] = React.useState(null);
|
|
3749
|
-
React.useEffect(() => {
|
|
3750
|
-
if (!pos) return;
|
|
3751
|
-
const close = () => setPos(null);
|
|
3752
|
-
const k = (e) => {
|
|
3753
|
-
if (e.key === "Escape") setPos(null);
|
|
3754
|
-
};
|
|
3755
|
-
document.addEventListener("click", close);
|
|
3756
|
-
document.addEventListener("keydown", k);
|
|
3757
|
-
return () => {
|
|
3758
|
-
document.removeEventListener("click", close);
|
|
3759
|
-
document.removeEventListener("keydown", k);
|
|
3760
|
-
};
|
|
3761
|
-
}, [pos]);
|
|
3762
|
-
return /* @__PURE__ */ React.createElement(
|
|
3763
|
-
"div",
|
|
3764
|
-
{
|
|
3765
|
-
className: cx("cs-ctxmenu-zone", className),
|
|
3766
|
-
onContextMenu: (e) => {
|
|
3767
|
-
e.preventDefault();
|
|
3768
|
-
const r = e.currentTarget.getBoundingClientRect();
|
|
3769
|
-
setPos({ x: e.clientX - r.left, y: e.clientY - r.top });
|
|
3770
|
-
}
|
|
3771
|
-
},
|
|
3772
|
-
children,
|
|
3773
|
-
pos ? /* @__PURE__ */ React.createElement("div", { className: "cs-menu__list", role: "menu", style: { position: "absolute", insetInlineStart: pos.x, insetBlockStart: pos.y } }, items.map((it, i) => it === "-" ? /* @__PURE__ */ React.createElement("div", { key: i, className: "cs-menu__sep" }) : /* @__PURE__ */ React.createElement("button", { key: i, type: "button", role: "menuitem", className: cx("cs-menu__item", it.danger && "cs-menu__item--danger"), onClick: () => {
|
|
3774
|
-
setPos(null);
|
|
3775
|
-
it.onSelect && it.onSelect();
|
|
3776
|
-
} }, it.label))) : null
|
|
3777
|
-
);
|
|
3778
|
-
}
|
|
3779
|
-
Object.assign(__ds_scope, { ContextMenu });
|
|
3780
|
-
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/overlays/ContextMenu.jsx", error: String((e && e.message) || e) }); }
|
|
3781
|
-
|
|
3782
4105
|
// components/overlays/Drawer.jsx
|
|
3783
4106
|
try { (() => {
|
|
3784
4107
|
const { makeT, useLang } = __ds_scope;
|
|
3785
4108
|
const { cx } = __ds_scope;
|
|
4109
|
+
const { useOverlayLayer } = __ds_scope;
|
|
3786
4110
|
function Drawer({ open, onClose, title, side = "right", children, actions, lang, className }) {
|
|
3787
4111
|
const [ref, L] = useLang(lang);
|
|
3788
|
-
React.
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
return;
|
|
3799
|
-
}
|
|
3800
|
-
if (e.key !== "Tab" || !ref.current) return;
|
|
3801
|
-
const f = [...ref.current.querySelectorAll(SEL)];
|
|
3802
|
-
if (!f.length) return;
|
|
3803
|
-
const a = f[0], z = f[f.length - 1];
|
|
3804
|
-
if (e.shiftKey && document.activeElement === a) {
|
|
3805
|
-
e.preventDefault();
|
|
3806
|
-
z.focus();
|
|
3807
|
-
} else if (!e.shiftKey && document.activeElement === z) {
|
|
3808
|
-
e.preventDefault();
|
|
3809
|
-
a.focus();
|
|
3810
|
-
}
|
|
3811
|
-
};
|
|
3812
|
-
document.addEventListener("keydown", k);
|
|
3813
|
-
return () => {
|
|
3814
|
-
document.removeEventListener("keydown", k);
|
|
3815
|
-
if (prev && prev.focus) prev.focus();
|
|
3816
|
-
};
|
|
3817
|
-
}, [open]);
|
|
4112
|
+
const panel = React.useRef(null);
|
|
4113
|
+
const closeRef = React.useRef(onClose);
|
|
4114
|
+
closeRef.current = onClose;
|
|
4115
|
+
useOverlayLayer({
|
|
4116
|
+
open: !!open,
|
|
4117
|
+
kind: "modal",
|
|
4118
|
+
trapFocus: true,
|
|
4119
|
+
onEscape: () => closeRef.current && closeRef.current(),
|
|
4120
|
+
panelRef: panel
|
|
4121
|
+
});
|
|
3818
4122
|
const t = makeT("Drawer", L);
|
|
3819
4123
|
if (!open) return null;
|
|
3820
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "cs-drawer-scrim", onClick: onClose, "aria-hidden": "true" }), /* @__PURE__ */ React.createElement(
|
|
4124
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "cs-drawer-scrim", onClick: onClose, "aria-hidden": "true" }), /* @__PURE__ */ React.createElement(
|
|
4125
|
+
"aside",
|
|
4126
|
+
{
|
|
4127
|
+
ref: (el) => {
|
|
4128
|
+
panel.current = el;
|
|
4129
|
+
ref.current = el;
|
|
4130
|
+
},
|
|
4131
|
+
tabIndex: -1,
|
|
4132
|
+
className: cx("cs-drawer", side === "left" && "cs-drawer--left", className),
|
|
4133
|
+
role: "dialog",
|
|
4134
|
+
"aria-modal": "true",
|
|
4135
|
+
"aria-label": typeof title === "string" ? title : t("panel")
|
|
4136
|
+
},
|
|
4137
|
+
/* @__PURE__ */ React.createElement("div", { className: "cs-drawer__header" }, title ? /* @__PURE__ */ React.createElement("h2", { className: "cs-drawer__title" }, title) : null, /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-drawer__close", "aria-label": t("close"), onClick: onClose }, /* @__PURE__ */ React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M6 6l12 12M18 6L6 18" })))),
|
|
4138
|
+
/* @__PURE__ */ React.createElement("div", { className: "cs-drawer__body", tabIndex: 0 }, children),
|
|
4139
|
+
actions ? /* @__PURE__ */ React.createElement("div", { className: "cs-drawer__footer" }, actions) : null
|
|
4140
|
+
));
|
|
3821
4141
|
}
|
|
3822
4142
|
Object.assign(__ds_scope, { Drawer });
|
|
3823
4143
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/overlays/Drawer.jsx", error: String((e && e.message) || e) }); }
|
|
3824
4144
|
|
|
3825
|
-
// components/overlays/HoverCard.jsx
|
|
3826
|
-
try { (() => {
|
|
3827
|
-
const { cx } = __ds_scope;
|
|
3828
|
-
function HoverCard({ trigger, children, openDelay = 150, closeDelay = 200, className }) {
|
|
3829
|
-
const [open, setOpen] = React.useState(false);
|
|
3830
|
-
const t1 = React.useRef();
|
|
3831
|
-
const t2 = React.useRef();
|
|
3832
|
-
const show = () => {
|
|
3833
|
-
clearTimeout(t2.current);
|
|
3834
|
-
t1.current = setTimeout(() => setOpen(true), openDelay);
|
|
3835
|
-
};
|
|
3836
|
-
const hide = () => {
|
|
3837
|
-
clearTimeout(t1.current);
|
|
3838
|
-
t2.current = setTimeout(() => setOpen(false), closeDelay);
|
|
3839
|
-
};
|
|
3840
|
-
React.useEffect(() => () => {
|
|
3841
|
-
clearTimeout(t1.current);
|
|
3842
|
-
clearTimeout(t2.current);
|
|
3843
|
-
}, []);
|
|
3844
|
-
return /* @__PURE__ */ React.createElement("span", { className: cx("cs-hovercard", className), onMouseEnter: show, onMouseLeave: hide, onFocus: show, onBlur: hide }, trigger, open ? /* @__PURE__ */ React.createElement("span", { className: "cs-hovercard__panel", role: "dialog" }, children) : null);
|
|
3845
|
-
}
|
|
3846
|
-
Object.assign(__ds_scope, { HoverCard });
|
|
3847
|
-
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/overlays/HoverCard.jsx", error: String((e && e.message) || e) }); }
|
|
3848
|
-
|
|
3849
4145
|
// components/overlays/Popconfirm.jsx
|
|
3850
4146
|
try { (() => {
|
|
3851
4147
|
const { makeT, useLang } = __ds_scope;
|
|
@@ -3937,30 +4233,37 @@ const { cx } = __ds_scope;
|
|
|
3937
4233
|
function Tour({ steps = [], open, onClose, lang, className }) {
|
|
3938
4234
|
const [i, setI] = React.useState(0);
|
|
3939
4235
|
const [rect, setRect] = React.useState(null);
|
|
4236
|
+
const [pop, setPop] = React.useState({ top: 80, left: 40 });
|
|
3940
4237
|
const [ref, L] = useLang(lang);
|
|
3941
4238
|
const t = makeT("Tour", L);
|
|
3942
4239
|
React.useEffect(() => {
|
|
3943
4240
|
if (open) setI(0);
|
|
3944
4241
|
}, [open]);
|
|
3945
4242
|
React.useEffect(() => {
|
|
3946
|
-
if (!open || !steps[i]) return;
|
|
4243
|
+
if (!open || !steps[i]) return void 0;
|
|
3947
4244
|
const el = document.querySelector(steps[i].target);
|
|
3948
4245
|
if (el) {
|
|
3949
4246
|
const r = el.getBoundingClientRect();
|
|
3950
|
-
|
|
3951
|
-
|
|
4247
|
+
const next = { x: r.left - 6, y: r.top - 6, w: r.width + 12, h: r.height + 12 };
|
|
4248
|
+
setRect(next);
|
|
4249
|
+
setPop({
|
|
4250
|
+
top: Math.min(window.innerHeight - 170, next.y + next.h + 12),
|
|
4251
|
+
left: Math.max(12, Math.min(window.innerWidth - 292, next.x))
|
|
4252
|
+
});
|
|
4253
|
+
} else {
|
|
4254
|
+
setRect(null);
|
|
4255
|
+
setPop({ top: 80, left: 40 });
|
|
4256
|
+
}
|
|
3952
4257
|
const k = (e) => {
|
|
3953
4258
|
if (e.key === "Escape") onClose && onClose();
|
|
3954
4259
|
};
|
|
3955
4260
|
document.addEventListener("keydown", k);
|
|
3956
4261
|
return () => document.removeEventListener("keydown", k);
|
|
3957
|
-
}, [open, i, steps]);
|
|
4262
|
+
}, [open, i, steps, onClose]);
|
|
3958
4263
|
if (!open || !steps.length) return /* @__PURE__ */ React.createElement("span", { ref, style: { display: "none" } });
|
|
3959
4264
|
const s = steps[i];
|
|
3960
4265
|
const last = i === steps.length - 1;
|
|
3961
|
-
|
|
3962
|
-
const popLeft = rect ? Math.max(12, Math.min(window.innerWidth - 292, rect.x)) : 40;
|
|
3963
|
-
return /* @__PURE__ */ React.createElement("div", { ref, className: cx("cs-tour", className) }, /* @__PURE__ */ React.createElement("div", { className: "cs-tour__scrim", onClick: onClose }), rect ? /* @__PURE__ */ React.createElement("div", { className: "cs-tour__hole", style: { left: rect.x, top: rect.y, width: rect.w, height: rect.h } }) : null, /* @__PURE__ */ React.createElement("div", { className: "cs-tour__pop", role: "dialog", "aria-label": typeof s.title === "string" ? s.title : void 0, style: { left: popLeft, top: popTop } }, /* @__PURE__ */ React.createElement("b", null, s.title), s.body ? /* @__PURE__ */ React.createElement("p", null, s.body) : null, /* @__PURE__ */ React.createElement("div", { className: "cs-tour__bar" }, /* @__PURE__ */ React.createElement("span", { className: "cs-tour__count" }, i + 1 + " / " + steps.length), /* @__PURE__ */ React.createElement("span", { className: "cs-tour__btns" }, /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-button cs-button--ghost cs-button--xs", onClick: onClose }, t("skip")), i > 0 ? /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-button cs-button--secondary cs-button--xs", onClick: () => setI(i - 1) }, t("back")) : null, /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-button cs-button--primary cs-button--xs", onClick: () => last ? onClose && onClose() : setI(i + 1) }, last ? t("done") : t("next"))))));
|
|
4266
|
+
return /* @__PURE__ */ React.createElement("div", { ref, className: cx("cs-tour", className) }, /* @__PURE__ */ React.createElement("div", { className: "cs-tour__scrim", onClick: onClose }), rect ? /* @__PURE__ */ React.createElement("div", { className: "cs-tour__hole", style: { left: rect.x, top: rect.y, width: rect.w, height: rect.h } }) : null, /* @__PURE__ */ React.createElement("div", { className: "cs-tour__pop", role: "dialog", "aria-label": typeof s.title === "string" ? s.title : void 0, style: { left: pop.left, top: pop.top } }, /* @__PURE__ */ React.createElement("b", null, s.title), s.body ? /* @__PURE__ */ React.createElement("p", null, s.body) : null, /* @__PURE__ */ React.createElement("div", { className: "cs-tour__bar" }, /* @__PURE__ */ React.createElement("span", { className: "cs-tour__count" }, i + 1 + " / " + steps.length), /* @__PURE__ */ React.createElement("span", { className: "cs-tour__btns" }, /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-button cs-button--ghost cs-button--xs", onClick: onClose }, t("skip")), i > 0 ? /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-button cs-button--secondary cs-button--xs", onClick: () => setI(i - 1) }, t("back")) : null, /* @__PURE__ */ React.createElement("button", { type: "button", className: "cs-button cs-button--primary cs-button--xs", onClick: () => last ? onClose && onClose() : setI(i + 1) }, last ? t("done") : t("next"))))));
|
|
3964
4267
|
}
|
|
3965
4268
|
Object.assign(__ds_scope, { Tour });
|
|
3966
4269
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/overlays/Tour.jsx", error: String((e && e.message) || e) }); }
|
|
@@ -4657,7 +4960,12 @@ try { (() => {
|
|
|
4657
4960
|
y: stored && Number.isFinite(stored.y) ? stored.y : 0
|
|
4658
4961
|
};
|
|
4659
4962
|
}
|
|
4660
|
-
|
|
4963
|
+
const authoring = typeof window !== "undefined" && typeof window.__dcSetProps === "function";
|
|
4964
|
+
const phEn = this.getAttribute("placeholder") || "Drop an image";
|
|
4965
|
+
const phVi = this.getAttribute("placeholder-vi") || "Thả ảnh (không bắt buộc)";
|
|
4966
|
+
const lang = (document.documentElement.getAttribute("lang") || "").toLowerCase();
|
|
4967
|
+
this._cap.textContent = authoring ? lang.startsWith("vi") ? phVi : phEn : "";
|
|
4968
|
+
if (this._cap) this._cap.style.display = authoring ? "" : "none";
|
|
4661
4969
|
const credit = (this.getAttribute("credit") || "").trim();
|
|
4662
4970
|
const attrError = !!(!credit && !this._userUrl && srcAttr && isUnsplashHost(srcAttr));
|
|
4663
4971
|
this.toggleAttribute("data-attribution-error", attrError);
|
|
@@ -4737,7 +5045,7 @@ try { (() => {
|
|
|
4737
5045
|
const tokens = {
|
|
4738
5046
|
"$meta": {
|
|
4739
5047
|
"system": "CyberSkill Design System",
|
|
4740
|
-
"version": "1.
|
|
5048
|
+
"version": "1.2.0",
|
|
4741
5049
|
"generated": "2026-07-23",
|
|
4742
5050
|
"note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
|
|
4743
5051
|
},
|
|
@@ -4756,6 +5064,10 @@ const tokens = {
|
|
|
4756
5064
|
"--cs-color-semantic-danger": "#B42318",
|
|
4757
5065
|
"--cs-color-semantic-warning": "#92400E",
|
|
4758
5066
|
"--cs-color-semantic-info": "#1D4ED8",
|
|
5067
|
+
"--cs-color-semantic-success-fg": "#FFFFFF",
|
|
5068
|
+
"--cs-color-semantic-danger-fg": "#FFFFFF",
|
|
5069
|
+
"--cs-color-semantic-warning-fg": "#FFFFFF",
|
|
5070
|
+
"--cs-color-semantic-info-fg": "#FFFFFF",
|
|
4759
5071
|
"--cs-color-accent-ochre": "#F4BA17",
|
|
4760
5072
|
"--cs-color-border-default": "#E7D9C6",
|
|
4761
5073
|
"--cs-color-link": "#6E3B0E",
|
|
@@ -4785,7 +5097,8 @@ const tokens = {
|
|
|
4785
5097
|
"--cs-component-textfield-border-default": "#BFA58F",
|
|
4786
5098
|
"--cs-component-textfield-paddingY": "10px",
|
|
4787
5099
|
"--cs-component-textfield-paddingX": "12px",
|
|
4788
|
-
"--cs-component-textfield-minHeight": "44px"
|
|
5100
|
+
"--cs-component-textfield-minHeight": "44px",
|
|
5101
|
+
"--cs-focus-ring": "3px"
|
|
4789
5102
|
},
|
|
4790
5103
|
"accent": {
|
|
4791
5104
|
"--cs-accent": "#F4BA17",
|
|
@@ -4796,7 +5109,8 @@ const tokens = {
|
|
|
4796
5109
|
"--cs-accent-ink": "#45210E",
|
|
4797
5110
|
"--cs-accent-glow": "rgba(244, 186, 23, 0.48)",
|
|
4798
5111
|
"--cs-accent-grad-a": "#F4BA17",
|
|
4799
|
-
"--cs-accent-grad-b": "#FCAF91"
|
|
5112
|
+
"--cs-accent-grad-b": "#FCAF91",
|
|
5113
|
+
"--cs-accent-on-strong": "#1A1108"
|
|
4800
5114
|
},
|
|
4801
5115
|
"depth": {
|
|
4802
5116
|
"--cs-depth-bg": "0",
|
|
@@ -4804,7 +5118,9 @@ const tokens = {
|
|
|
4804
5118
|
"--cs-depth-card": "10",
|
|
4805
5119
|
"--cs-depth-nav": "50",
|
|
4806
5120
|
"--cs-depth-modal": "100",
|
|
4807
|
-
"--cs-depth-toast": "200"
|
|
5121
|
+
"--cs-depth-toast": "200",
|
|
5122
|
+
"--cs-depth-dropdown": "60",
|
|
5123
|
+
"--cs-depth-overlay": "80"
|
|
4808
5124
|
},
|
|
4809
5125
|
"glass": {
|
|
4810
5126
|
"--cs-glass-whisper-blur": "8px",
|
|
@@ -4869,7 +5185,8 @@ const tokens = {
|
|
|
4869
5185
|
"--cs-breakpoint-2xl": "1536px"
|
|
4870
5186
|
},
|
|
4871
5187
|
"container": {
|
|
4872
|
-
"--cs-container-max": "1320px"
|
|
5188
|
+
"--cs-container-max": "1320px",
|
|
5189
|
+
"--cs-prose-measure": "45rem"
|
|
4873
5190
|
},
|
|
4874
5191
|
"font": {
|
|
4875
5192
|
"--cs-font-family-ui": "'Be Vietnam Pro', ui-sans-serif, system-ui, sans-serif",
|
|
@@ -4883,6 +5200,7 @@ const tokens = {
|
|
|
4883
5200
|
"--cs-font-lineHeight-body": "1.5",
|
|
4884
5201
|
"--cs-font-lineHeight-heading": "1.35",
|
|
4885
5202
|
"--cs-font-lineHeight-tight": "1.15",
|
|
5203
|
+
"--cs-font-size-2xs": "0.6875rem",
|
|
4886
5204
|
"--cs-font-size-xs": "0.75rem",
|
|
4887
5205
|
"--cs-font-size-sm": "0.875rem",
|
|
4888
5206
|
"--cs-font-size-base": "1rem",
|
|
@@ -4903,6 +5221,7 @@ const tokens = {
|
|
|
4903
5221
|
"--cs-text-body-lg": "var(--cs-font-size-md)",
|
|
4904
5222
|
"--cs-text-body": "var(--cs-font-size-base)",
|
|
4905
5223
|
"--cs-text-secondary": "var(--cs-font-size-sm)",
|
|
5224
|
+
"--cs-text-micro": "var(--cs-font-size-2xs)",
|
|
4906
5225
|
"--cs-text-caption": "var(--cs-font-size-xs)",
|
|
4907
5226
|
"--cs-text-eyebrow": "var(--cs-font-size-xs)"
|
|
4908
5227
|
},
|
|
@@ -4921,6 +5240,12 @@ const tokens = {
|
|
|
4921
5240
|
"--cs-icon-sm": "16px",
|
|
4922
5241
|
"--cs-icon-md": "20px",
|
|
4923
5242
|
"--cs-icon-lg": "24px"
|
|
5243
|
+
},
|
|
5244
|
+
"doc": {
|
|
5245
|
+
"--cs-doc-ink": "#1A1614",
|
|
5246
|
+
"--cs-doc-slate": "#3F4C55",
|
|
5247
|
+
"--cs-doc-fill": "#FDE68A",
|
|
5248
|
+
"--cs-doc-fill-ink": "#1A1614"
|
|
4924
5249
|
}
|
|
4925
5250
|
},
|
|
4926
5251
|
"themes": {
|
|
@@ -4936,6 +5261,10 @@ const tokens = {
|
|
|
4936
5261
|
"--cs-color-semantic-danger": "#F87171",
|
|
4937
5262
|
"--cs-color-semantic-warning": "#FBBF24",
|
|
4938
5263
|
"--cs-color-semantic-info": "#7CB2FB",
|
|
5264
|
+
"--cs-color-semantic-success-fg": "#1a1108",
|
|
5265
|
+
"--cs-color-semantic-danger-fg": "#1a1108",
|
|
5266
|
+
"--cs-color-semantic-warning-fg": "#1a1108",
|
|
5267
|
+
"--cs-color-semantic-info-fg": "#1a1108",
|
|
4939
5268
|
"--cs-color-border-default": "#4a3a2c",
|
|
4940
5269
|
"--cs-color-link": "#f4ba17",
|
|
4941
5270
|
"--cs-color-link-hover": "#f5ead9",
|
|
@@ -4960,6 +5289,10 @@ const tokens = {
|
|
|
4960
5289
|
"--cs-color-semantic-danger": "#F87171",
|
|
4961
5290
|
"--cs-color-semantic-warning": "#FBBF24",
|
|
4962
5291
|
"--cs-color-semantic-info": "#7CB2FB",
|
|
5292
|
+
"--cs-color-semantic-success-fg": "#1a1108",
|
|
5293
|
+
"--cs-color-semantic-danger-fg": "#1a1108",
|
|
5294
|
+
"--cs-color-semantic-warning-fg": "#1a1108",
|
|
5295
|
+
"--cs-color-semantic-info-fg": "#1a1108",
|
|
4963
5296
|
"--cs-color-border-default": "#4a3a2c",
|
|
4964
5297
|
"--cs-color-link": "#f4ba17",
|
|
4965
5298
|
"--cs-color-link-hover": "#f5ead9",
|
|
@@ -4979,6 +5312,7 @@ const tokens = {
|
|
|
4979
5312
|
"--cs-accent-strong": "#90825E",
|
|
4980
5313
|
"--cs-accent-bright": "#F6EBCC",
|
|
4981
5314
|
"--cs-accent-on": "#292414",
|
|
5315
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
4982
5316
|
"--cs-accent-tint": "#FBF7EA",
|
|
4983
5317
|
"--cs-accent-ink": "#292414",
|
|
4984
5318
|
"--cs-accent-glow": "rgba(248, 233, 192, 0.48)",
|
|
@@ -4992,6 +5326,7 @@ const tokens = {
|
|
|
4992
5326
|
"--cs-accent-strong": "#A47D17",
|
|
4993
5327
|
"--cs-accent-bright": "#F4BA17",
|
|
4994
5328
|
"--cs-accent-on": "#45210E",
|
|
5329
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
4995
5330
|
"--cs-accent-tint": "#FBF4E9",
|
|
4996
5331
|
"--cs-accent-ink": "#45210E",
|
|
4997
5332
|
"--cs-accent-glow": "rgba(244, 186, 23, 0.48)",
|
|
@@ -5003,6 +5338,7 @@ const tokens = {
|
|
|
5003
5338
|
"--cs-accent-strong": "#201300",
|
|
5004
5339
|
"--cs-accent-bright": "#DEC7A2",
|
|
5005
5340
|
"--cs-accent-on": "#2D220E",
|
|
5341
|
+
"--cs-accent-on-strong": "#FFFFFF",
|
|
5006
5342
|
"--cs-accent-tint": "#FFF6E7",
|
|
5007
5343
|
"--cs-accent-ink": "#2D220E",
|
|
5008
5344
|
"--cs-accent-glow": "rgba(81, 56, 1, 0.48)",
|
|
@@ -5016,6 +5352,7 @@ const tokens = {
|
|
|
5016
5352
|
"--cs-accent-strong": "#967C75",
|
|
5017
5353
|
"--cs-accent-bright": "#FCE6DF",
|
|
5018
5354
|
"--cs-accent-on": "#2C211E",
|
|
5355
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
5019
5356
|
"--cs-accent-tint": "#FEF4F2",
|
|
5020
5357
|
"--cs-accent-ink": "#2C211E",
|
|
5021
5358
|
"--cs-accent-glow": "rgba(255, 225, 216, 0.48)",
|
|
@@ -5029,6 +5366,7 @@ const tokens = {
|
|
|
5029
5366
|
"--cs-accent-strong": "#B47054",
|
|
5030
5367
|
"--cs-accent-bright": "#FED3C3",
|
|
5031
5368
|
"--cs-accent-on": "#381B10",
|
|
5369
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
5032
5370
|
"--cs-accent-tint": "#FFF4F0",
|
|
5033
5371
|
"--cs-accent-ink": "#381B10",
|
|
5034
5372
|
"--cs-accent-glow": "rgba(252, 175, 145, 0.48)",
|
|
@@ -5042,6 +5380,7 @@ const tokens = {
|
|
|
5042
5380
|
"--cs-accent-strong": "#280D00",
|
|
5043
5381
|
"--cs-accent-bright": "#F1BEA4",
|
|
5044
5382
|
"--cs-accent-on": "#361D0F",
|
|
5383
|
+
"--cs-accent-on-strong": "#FFFFFF",
|
|
5045
5384
|
"--cs-accent-tint": "#FFF4EF",
|
|
5046
5385
|
"--cs-accent-ink": "#361D0F",
|
|
5047
5386
|
"--cs-accent-glow": "rgba(98, 43, 6, 0.48)",
|
|
@@ -5055,6 +5394,7 @@ const tokens = {
|
|
|
5055
5394
|
"--cs-accent-strong": "#5A8A90",
|
|
5056
5395
|
"--cs-accent-bright": "#CDF4F9",
|
|
5057
5396
|
"--cs-accent-on": "#13282B",
|
|
5397
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
5058
5398
|
"--cs-accent-tint": "#EBFAFC",
|
|
5059
5399
|
"--cs-accent-ink": "#13282B",
|
|
5060
5400
|
"--cs-accent-glow": "rgba(192, 245, 252, 0.48)",
|
|
@@ -5068,6 +5408,7 @@ const tokens = {
|
|
|
5068
5408
|
"--cs-accent-strong": "#108EA0",
|
|
5069
5409
|
"--cs-accent-bright": "#99EEFF",
|
|
5070
5410
|
"--cs-accent-on": "#012A30",
|
|
5411
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
5071
5412
|
"--cs-accent-tint": "#E7FBFF",
|
|
5072
5413
|
"--cs-accent-ink": "#012A30",
|
|
5073
5414
|
"--cs-accent-glow": "rgba(46, 219, 247, 0.48)",
|
|
@@ -5081,6 +5422,7 @@ const tokens = {
|
|
|
5081
5422
|
"--cs-accent-strong": "#011A21",
|
|
5082
5423
|
"--cs-accent-bright": "#A8D3E0",
|
|
5083
5424
|
"--cs-accent-on": "#10282F",
|
|
5425
|
+
"--cs-accent-on-strong": "#FFFFFF",
|
|
5084
5426
|
"--cs-accent-tint": "#EAFAFF",
|
|
5085
5427
|
"--cs-accent-ink": "#10282F",
|
|
5086
5428
|
"--cs-accent-glow": "rgba(0, 69, 84, 0.48)",
|
|
@@ -5094,6 +5436,7 @@ const tokens = {
|
|
|
5094
5436
|
"--cs-accent-strong": "#7C8965",
|
|
5095
5437
|
"--cs-accent-bright": "#E5F1D2",
|
|
5096
5438
|
"--cs-accent-on": "#212617",
|
|
5439
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
5097
5440
|
"--cs-accent-tint": "#F4F9ED",
|
|
5098
5441
|
"--cs-accent-ink": "#212617",
|
|
5099
5442
|
"--cs-accent-glow": "rgba(225, 241, 200, 0.48)",
|
|
@@ -5107,6 +5450,7 @@ const tokens = {
|
|
|
5107
5450
|
"--cs-accent-strong": "#629122",
|
|
5108
5451
|
"--cs-accent-bright": "#C5ED9C",
|
|
5109
5452
|
"--cs-accent-on": "#182A00",
|
|
5453
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
5110
5454
|
"--cs-accent-tint": "#EFFCE3",
|
|
5111
5455
|
"--cs-accent-ink": "#182A00",
|
|
5112
5456
|
"--cs-accent-glow": "rgba(163, 215, 104, 0.48)",
|
|
@@ -5120,6 +5464,7 @@ const tokens = {
|
|
|
5120
5464
|
"--cs-accent-strong": "#051D00",
|
|
5121
5465
|
"--cs-accent-bright": "#B0D8A3",
|
|
5122
5466
|
"--cs-accent-on": "#162A0E",
|
|
5467
|
+
"--cs-accent-on-strong": "#FFFFFF",
|
|
5123
5468
|
"--cs-accent-tint": "#ECFDE7",
|
|
5124
5469
|
"--cs-accent-ink": "#162A0E",
|
|
5125
5470
|
"--cs-accent-glow": "rgba(26, 74, 1, 0.48)",
|
|
@@ -5133,6 +5478,7 @@ const tokens = {
|
|
|
5133
5478
|
"--cs-accent-strong": "#947F65",
|
|
5134
5479
|
"--cs-accent-bright": "#FBE8D2",
|
|
5135
5480
|
"--cs-accent-on": "#2B2217",
|
|
5481
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
5136
5482
|
"--cs-accent-tint": "#FDF5ED",
|
|
5137
5483
|
"--cs-accent-ink": "#2B2217",
|
|
5138
5484
|
"--cs-accent-glow": "rgba(254, 229, 199, 0.48)",
|
|
@@ -5146,6 +5492,7 @@ const tokens = {
|
|
|
5146
5492
|
"--cs-accent-strong": "#AC780B",
|
|
5147
5493
|
"--cs-accent-bright": "#FDD89F",
|
|
5148
5494
|
"--cs-accent-on": "#312002",
|
|
5495
|
+
"--cs-accent-on-strong": "#1A1108",
|
|
5149
5496
|
"--cs-accent-tint": "#FFF5E7",
|
|
5150
5497
|
"--cs-accent-ink": "#312002",
|
|
5151
5498
|
"--cs-accent-glow": "rgba(243, 185, 88, 0.48)",
|
|
@@ -5159,6 +5506,7 @@ const tokens = {
|
|
|
5159
5506
|
"--cs-accent-strong": "#1F1400",
|
|
5160
5507
|
"--cs-accent-bright": "#DCC8A2",
|
|
5161
5508
|
"--cs-accent-on": "#2D220E",
|
|
5509
|
+
"--cs-accent-on-strong": "#FFFFFF",
|
|
5162
5510
|
"--cs-accent-tint": "#FEF6E7",
|
|
5163
5511
|
"--cs-accent-ink": "#2D220E",
|
|
5164
5512
|
"--cs-accent-glow": "rgba(80, 57, 1, 0.48)",
|
|
@@ -5302,7 +5650,40 @@ function StatusHub() {
|
|
|
5302
5650
|
}, [D, q, facet, kpi]);
|
|
5303
5651
|
const maxV = Math.max(...D.velocity.map((v) => v.n));
|
|
5304
5652
|
const toggleKpi = (k) => setKpi((cur) => cur === k ? null : k);
|
|
5305
|
-
return /* @__PURE__ */ React.createElement("div", { className: "sh", lang, "data-theme": dark ? "dark" : void 0 }, /* @__PURE__ */ React.createElement("header", { className: "hd" }, /* @__PURE__ */ React.createElement("div", { className: "hd-in" }, /* @__PURE__ */ React.createElement("div", { className: "hd-id" }, /* @__PURE__ */ React.createElement("span", { className: "hd-mark" }, /* @__PURE__ */ React.createElement("img", { src: "../../assets/logo-mark.svg", alt: "" })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h1", null, "Status Hub"), /* @__PURE__ */ React.createElement("p", { className: "hd-sub" }, t.sub))), /* @__PURE__ */ React.createElement("div", { className: "hd-side" }, /* @__PURE__ */ React.createElement("p", { className: "hd-meta" }, t.updated, /* @__PURE__ */ React.createElement("br", null), VI ? VI.updated : D.updated), /* @__PURE__ */ React.createElement("button", { className: "btn ghost", onClick: () => setLang((l) => l === "en" ? "vi" : "en"), "aria-label": "Toggle language", style: { fontWeight: 700, fontSize: 13 } }, t.langBtn), /* @__PURE__ */ React.createElement("button", { className: "btn ghost", onClick: () => setDark((v) => !v), "aria-label": t.theme }, /* @__PURE__ */ React.createElement(ThemeGlyph, { dark }))))), /* @__PURE__ */ React.createElement("
|
|
5653
|
+
return /* @__PURE__ */ React.createElement("div", { className: "sh", lang, "data-theme": dark ? "dark" : void 0 }, /* @__PURE__ */ React.createElement("a", { className: "cs-skip", href: "#main", style: { position: "absolute", left: -999, width: 1, height: 1, overflow: "hidden" } }, "Skip to content"), /* @__PURE__ */ React.createElement("header", { className: "hd" }, /* @__PURE__ */ React.createElement("div", { className: "hd-in" }, /* @__PURE__ */ React.createElement("div", { className: "hd-id" }, /* @__PURE__ */ React.createElement("span", { className: "hd-mark" }, /* @__PURE__ */ React.createElement("img", { src: "../../assets/logo-mark.svg", alt: "" })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h1", null, "Status Hub"), /* @__PURE__ */ React.createElement("p", { className: "hd-sub" }, t.sub))), /* @__PURE__ */ React.createElement("div", { className: "hd-side" }, /* @__PURE__ */ React.createElement("p", { className: "hd-meta" }, t.updated, /* @__PURE__ */ React.createElement("br", null), VI ? VI.updated : D.updated), /* @__PURE__ */ React.createElement("button", { className: "btn ghost", onClick: () => setLang((l) => l === "en" ? "vi" : "en"), "aria-label": "Toggle language", style: { fontWeight: 700, fontSize: 13 } }, t.langBtn), /* @__PURE__ */ React.createElement("button", { className: "btn ghost", onClick: () => setDark((v) => !v), "aria-label": t.theme }, /* @__PURE__ */ React.createElement(ThemeGlyph, { dark }))))), /* @__PURE__ */ React.createElement("main", { id: "main", className: "wrap" }, /* @__PURE__ */ React.createElement("div", { className: "deck" }, /* @__PURE__ */ React.createElement("section", { className: "panel" }, /* @__PURE__ */ React.createElement("h2", null, t.portfolio), /* @__PURE__ */ React.createElement("div", { className: "kpis" }, /* @__PURE__ */ React.createElement("button", { className: "kpi", "data-on": kpi === null ? "1" : "0", onClick: () => setKpi(null) }, /* @__PURE__ */ React.createElement("b", null, counts.total), /* @__PURE__ */ React.createElement("span", null, t.projects)), /* @__PURE__ */ React.createElement("button", { className: "kpi", "data-on": kpi === "active" ? "1" : "0", onClick: () => toggleKpi("active") }, /* @__PURE__ */ React.createElement("b", null, counts.active), /* @__PURE__ */ React.createElement("span", null, t.inprog)), /* @__PURE__ */ React.createElement("button", { className: "kpi", "data-on": kpi === "done" ? "1" : "0", onClick: () => toggleKpi("done") }, /* @__PURE__ */ React.createElement("b", null, counts.done), /* @__PURE__ */ React.createElement("span", null, t.shipped)), /* @__PURE__ */ React.createElement("button", { className: "kpi", "data-on": kpi === "hold" ? "1" : "0", onClick: () => toggleKpi("hold") }, /* @__PURE__ */ React.createElement("b", null, counts.hold), /* @__PURE__ */ React.createElement("span", null, t.blocked)), /* @__PURE__ */ React.createElement("button", { className: "kpi", onClick: () => setKpi(null) }, /* @__PURE__ */ React.createElement("b", null, counts.avg, "%"), /* @__PURE__ */ React.createElement("span", null, t.avg))), /* @__PURE__ */ React.createElement(Segments, { seg: { done: 60, active: 22, hold: 6, todo: 12 }, className: "bar-seg" }), /* @__PURE__ */ React.createElement("div", { className: "legend" }, /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("i", { className: "dot", style: { background: "var(--cs-color-semantic-success)" } }), t.shipped), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("i", { className: "dot", style: { background: "var(--cs-color-brand-ochre)" } }), t.inprog), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("i", { className: "dot", style: { background: "var(--cs-color-semantic-danger)" } }), t.blocked), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("i", { className: "dot", style: { background: "var(--cs-status-todo)" } }), t.planned))), /* @__PURE__ */ React.createElement("section", { className: "panel" }, /* @__PURE__ */ React.createElement("h2", null, t.velocity), /* @__PURE__ */ React.createElement("div", { className: "spark" }, D.velocity.map((v) => /* @__PURE__ */ React.createElement("a", { key: v.wk, title: v.n + t.perShipped }, /* @__PURE__ */ React.createElement("b", null, v.n), /* @__PURE__ */ React.createElement("i", { style: { height: v.n / maxV * 72 + "px" } }), /* @__PURE__ */ React.createElement("span", null, v.wk)))))), /* @__PURE__ */ React.createElement("div", { className: "now" }, /* @__PURE__ */ React.createElement("h2", null, t.nowTitle), lang === "vi" ? /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("b", null, "v1.6.0 — Liên kết Glass + gói Ngũ Hành v2."), " Liên kết component ", /* @__PURE__ */ React.createElement("span", { className: "mono" }, ".cs-surface-*"), " (tùy chọn), trình kiểm 0 cảnh báo trên cả 15 gói, và kiểm tra lại APCA cho chế độ tối. Ra mắt tuần này.") : /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("b", null, "v1.6.0 — Glass bindings + element-pack v2."), " Opt-in ", /* @__PURE__ */ React.createElement("span", { className: "mono" }, ".cs-surface-*"), " component bindings, a zero-warning verifier across all 15 packs, and a dark-mode APCA re-check. Ships this week.")), /* @__PURE__ */ React.createElement("div", { className: "bar" }, /* @__PURE__ */ React.createElement("div", { className: "bar-top" }, /* @__PURE__ */ React.createElement("label", { className: "srch" }, /* @__PURE__ */ React.createElement(SearchGlyph, null), /* @__PURE__ */ React.createElement("input", { placeholder: t.search, value: q, onChange: (e) => setQ(e.target.value) })), /* @__PURE__ */ React.createElement(
|
|
5654
|
+
"div",
|
|
5655
|
+
{
|
|
5656
|
+
className: "lenses",
|
|
5657
|
+
role: "tablist",
|
|
5658
|
+
"aria-label": t.view,
|
|
5659
|
+
onKeyDown: (e) => {
|
|
5660
|
+
const order = ["board", "table", "releases"];
|
|
5661
|
+
const i = order.indexOf(lens);
|
|
5662
|
+
let next = i;
|
|
5663
|
+
if (e.key === "ArrowRight") next = (i + 1) % order.length;
|
|
5664
|
+
else if (e.key === "ArrowLeft") next = (i - 1 + order.length) % order.length;
|
|
5665
|
+
else if (e.key === "Home") next = 0;
|
|
5666
|
+
else if (e.key === "End") next = order.length - 1;
|
|
5667
|
+
else return;
|
|
5668
|
+
e.preventDefault();
|
|
5669
|
+
setLens(order[next]);
|
|
5670
|
+
const tabs = e.currentTarget.querySelectorAll('[role="tab"]');
|
|
5671
|
+
tabs[next] && tabs[next].focus && tabs[next].focus();
|
|
5672
|
+
}
|
|
5673
|
+
},
|
|
5674
|
+
["board", "table", "releases"].map((l) => /* @__PURE__ */ React.createElement(
|
|
5675
|
+
"button",
|
|
5676
|
+
{
|
|
5677
|
+
key: l,
|
|
5678
|
+
className: "ln",
|
|
5679
|
+
role: "tab",
|
|
5680
|
+
"aria-selected": lens === l,
|
|
5681
|
+
tabIndex: lens === l ? 0 : -1,
|
|
5682
|
+
onClick: () => setLens(l)
|
|
5683
|
+
},
|
|
5684
|
+
t.lenses[l]
|
|
5685
|
+
))
|
|
5686
|
+
), /* @__PURE__ */ React.createElement("label", { className: "facet" }, t.status, /* @__PURE__ */ React.createElement("select", { value: kpi || facet, onChange: (e) => {
|
|
5306
5687
|
setFacet(e.target.value);
|
|
5307
5688
|
setKpi(null);
|
|
5308
5689
|
} }, /* @__PURE__ */ React.createElement("option", { value: "all" }, t.all), /* @__PURE__ */ React.createElement("option", { value: "active" }, t.inprog), /* @__PURE__ */ React.createElement("option", { value: "done" }, t.shipped), /* @__PURE__ */ React.createElement("option", { value: "hold" }, t.blocked))), /* @__PURE__ */ React.createElement("span", { className: "cnt" }, shown.length, " ", t.of, " ", D.projects.length))), lens === "board" && /* @__PURE__ */ React.createElement("div", { className: "grid" }, shown.map((p0) => {
|
|
@@ -5499,15 +5880,35 @@ function Website() {
|
|
|
5499
5880
|
const [seed, setSeed] = useState("");
|
|
5500
5881
|
const [wish, setWish] = useState("");
|
|
5501
5882
|
const [sent, setSent] = useState(false);
|
|
5883
|
+
const [fabVisible, setFabVisible] = useState(false);
|
|
5502
5884
|
const t = window.SITE_COPY[loc];
|
|
5503
5885
|
function openChat(s) {
|
|
5504
5886
|
setSeed(s || "");
|
|
5505
5887
|
setChat(true);
|
|
5506
5888
|
}
|
|
5507
|
-
|
|
5889
|
+
useEffect(() => {
|
|
5890
|
+
const sync = () => setFabVisible(window.scrollY > 140);
|
|
5891
|
+
sync();
|
|
5892
|
+
window.addEventListener("scroll", sync, { passive: true });
|
|
5893
|
+
return () => window.removeEventListener("scroll", sync);
|
|
5894
|
+
}, []);
|
|
5895
|
+
return /* @__PURE__ */ React.createElement("div", { className: "site", "data-theme": dark ? "dark" : void 0 }, /* @__PURE__ */ React.createElement("a", { className: "cs-skip", href: "#main", style: { position: "absolute", left: -999, width: 1, height: 1, overflow: "hidden" } }, "Skip to content"), /* @__PURE__ */ React.createElement("header", { className: "hdr cs-surface-light" }, /* @__PURE__ */ React.createElement("div", { className: "container hdr-in" }, /* @__PURE__ */ React.createElement("a", { className: "brand", href: "#top" }, /* @__PURE__ */ React.createElement("img", { src: "../../assets/logo-mark.svg", alt: "" }), "CyberSkill"), /* @__PURE__ */ React.createElement("nav", { className: "nav" }, t.nav.map((n, i) => /* @__PURE__ */ React.createElement("a", { key: i, href: "#" + ["services", "work", "process", "careers", "contact"][i] }, n))), /* @__PURE__ */ React.createElement("div", { className: "hdr-side" }, /* @__PURE__ */ React.createElement("button", { className: "mini", onClick: () => setLoc(loc === "en" ? "vi" : "en") }, t.langLabel), /* @__PURE__ */ React.createElement("button", { className: "mini icon", onClick: () => setDark(!dark), "aria-label": "Toggle theme" }, /* @__PURE__ */ React.createElement(I, { name: dark ? "sun" : "moon", size: 18 })), /* @__PURE__ */ React.createElement("button", { className: "mini", style: { background: "var(--cs-color-brand-umber)", color: "var(--cs-color-text-inverse,#fff)", borderColor: "transparent" }, onClick: () => openChat("") }, t.talk)))), /* @__PURE__ */ React.createElement("main", { id: "main" }, /* @__PURE__ */ React.createElement("section", { className: "hero", id: "top" }, /* @__PURE__ */ React.createElement("div", { className: "container hero-in" }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "eyebrow" }, t.eyebrow), /* @__PURE__ */ React.createElement("h1", null, t.slogan), /* @__PURE__ */ React.createElement("div", { className: "vn" }, t.sub), /* @__PURE__ */ React.createElement("p", { className: "lead" }, t.lead), /* @__PURE__ */ React.createElement("div", { className: "wish" }, /* @__PURE__ */ React.createElement("input", { value: wish, onChange: (e) => setWish(e.target.value), onKeyDown: (e) => e.key === "Enter" && openChat(wish), placeholder: t.wishPlaceholder, "aria-label": t.wishPlaceholder }), /* @__PURE__ */ React.createElement("button", { className: "btn-gold", onClick: () => openChat(wish) }, /* @__PURE__ */ React.createElement(I, { name: "sparkle", size: 18 }), t.wishCta))), /* @__PURE__ */ React.createElement("div", { className: "hero-art" }, /* @__PURE__ */ React.createElement("img", { src: "../../assets/lumi-poster.webp", alt: "Lumi, the golden genie" })))), /* @__PURE__ */ React.createElement("div", { className: "marq" }, /* @__PURE__ */ React.createElement("div", { className: "container marq-in" }, t.marquee.map((m, i) => /* @__PURE__ */ React.createElement(React.Fragment, { key: i }, i > 0 && /* @__PURE__ */ React.createElement("b", null, "·"), /* @__PURE__ */ React.createElement("span", null, m))))), /* @__PURE__ */ React.createElement("section", { className: "sec", id: "services" }, /* @__PURE__ */ React.createElement("div", { className: "container" }, /* @__PURE__ */ React.createElement("div", { className: "eyebrow" }, t.nav[0]), /* @__PURE__ */ React.createElement("h2", null, t.servicesTitle), /* @__PURE__ */ React.createElement("p", { className: "sec-lead" }, t.servicesLead), /* @__PURE__ */ React.createElement("div", { className: "svc-grid" }, t.services.map((s, i) => /* @__PURE__ */ React.createElement("article", { className: "svc cs-surface-standard", key: i }, /* @__PURE__ */ React.createElement("div", { className: "svc-ic" }, /* @__PURE__ */ React.createElement(I, { name: s.icon })), /* @__PURE__ */ React.createElement("h3", null, s.t), /* @__PURE__ */ React.createElement("p", null, s.s), /* @__PURE__ */ React.createElement("ul", null, s.o.map((o) => /* @__PURE__ */ React.createElement("li", { key: o }, o)))))))), /* @__PURE__ */ React.createElement("section", { className: "sec sec-alt", id: "process" }, /* @__PURE__ */ React.createElement("div", { className: "container" }, /* @__PURE__ */ React.createElement("div", { className: "eyebrow" }, t.nav[2]), /* @__PURE__ */ React.createElement("h2", null, t.processTitle), /* @__PURE__ */ React.createElement("p", { className: "sec-lead" }, t.processLead), /* @__PURE__ */ React.createElement("div", { className: "steps" }, t.steps.map((s) => /* @__PURE__ */ React.createElement("div", { className: "step", key: s.n }, /* @__PURE__ */ React.createElement("span", { className: "n" }, s.n), /* @__PURE__ */ React.createElement("h3", null, s.t), /* @__PURE__ */ React.createElement("p", null, s.s)))))), /* @__PURE__ */ React.createElement("section", { className: "sec", id: "careers" }, /* @__PURE__ */ React.createElement("div", { className: "container" }, /* @__PURE__ */ React.createElement("div", { className: "band" }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h2", null, t.careersTitle), /* @__PURE__ */ React.createElement("p", null, t.careersLead)), /* @__PURE__ */ React.createElement("button", { className: "btn-gold", onClick: () => openChat("") }, t.careersCta, /* @__PURE__ */ React.createElement(I, { name: "arrow-right", size: 18 }))))), /* @__PURE__ */ React.createElement("section", { className: "sec sec-alt", id: "contact" }, /* @__PURE__ */ React.createElement("div", { className: "container contact-grid" }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "eyebrow" }, t.nav[4]), /* @__PURE__ */ React.createElement("h2", null, t.contactTitle), /* @__PURE__ */ React.createElement("p", { className: "sec-lead", style: { marginBottom: 16 } }, t.contactLead), /* @__PURE__ */ React.createElement("p", { className: "trust" }, /* @__PURE__ */ React.createElement(I, { name: "check", size: 16 }), t.form.trust)), sent ? /* @__PURE__ */ React.createElement("div", { className: "sent" }, /* @__PURE__ */ React.createElement(I, { name: "check", size: 18 }), " ", loc === "vi" ? "Đã nhận được lời nhắn. Cảm ơn bạn!" : "Message received. Thank you!") : /* @__PURE__ */ React.createElement("form", { className: "form", onSubmit: (e) => {
|
|
5508
5896
|
e.preventDefault();
|
|
5509
5897
|
setSent(true);
|
|
5510
|
-
} }, /* @__PURE__ */ React.createElement("label", { className: "cs-field" }, /* @__PURE__ */ React.createElement("span", { className: "cs-field__label" }, t.form.name), /* @__PURE__ */ React.createElement("input", { className: "cs-field__control", required: true })), /* @__PURE__ */ React.createElement("label", { className: "cs-field" }, /* @__PURE__ */ React.createElement("span", { className: "cs-field__label" }, t.form.email), /* @__PURE__ */ React.createElement("input", { className: "cs-field__control", type: "email", required: true })), /* @__PURE__ */ React.createElement("label", { className: "cs-field" }, /* @__PURE__ */ React.createElement("span", { className: "cs-field__label" }, t.form.company, " ", /* @__PURE__ */ React.createElement("span", { className: "muted", style: { fontWeight: 400, color: "var(--cs-color-text-muted)" } }, "· ", t.form.optional)), /* @__PURE__ */ React.createElement("input", { className: "cs-field__control" })), /* @__PURE__ */ React.createElement("label", { className: "cs-field" }, /* @__PURE__ */ React.createElement("span", { className: "cs-field__label" }, t.form.message), /* @__PURE__ */ React.createElement("textarea", { className: "cs-field__control", rows: "3" })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("button", { type: "submit", className: "btn-gold" }, t.form.submit, /* @__PURE__ */ React.createElement(I, { name: "arrow-right", size: 18 })))))), /* @__PURE__ */ React.createElement("footer", { className: "ft" }, /* @__PURE__ */ React.createElement("div", { className: "container ft-in" }, /* @__PURE__ */ React.createElement("a", { className: "brand", href: "#top" }, /* @__PURE__ */ React.createElement("img", { src: "../../assets/logo-mark.svg", alt: "" }), "CyberSkill"), /* @__PURE__ */ React.createElement("div", { className: "ft-links" }, t.footerLinks.map((l) => /* @__PURE__ */ React.createElement("a", { key: l, href: "#top" }, l))), /* @__PURE__ */ React.createElement("small", null, "© 2026 CyberSkill · ", t.footerRights, " · Saigon"))), !chat && /* @__PURE__ */ React.createElement(
|
|
5898
|
+
} }, /* @__PURE__ */ React.createElement("label", { className: "cs-field" }, /* @__PURE__ */ React.createElement("span", { className: "cs-field__label" }, t.form.name), /* @__PURE__ */ React.createElement("input", { className: "cs-field__control", required: true })), /* @__PURE__ */ React.createElement("label", { className: "cs-field" }, /* @__PURE__ */ React.createElement("span", { className: "cs-field__label" }, t.form.email), /* @__PURE__ */ React.createElement("input", { className: "cs-field__control", type: "email", required: true })), /* @__PURE__ */ React.createElement("label", { className: "cs-field" }, /* @__PURE__ */ React.createElement("span", { className: "cs-field__label" }, t.form.company, " ", /* @__PURE__ */ React.createElement("span", { className: "muted", style: { fontWeight: 400, color: "var(--cs-color-text-muted)" } }, "· ", t.form.optional)), /* @__PURE__ */ React.createElement("input", { className: "cs-field__control" })), /* @__PURE__ */ React.createElement("label", { className: "cs-field" }, /* @__PURE__ */ React.createElement("span", { className: "cs-field__label" }, t.form.message), /* @__PURE__ */ React.createElement("textarea", { className: "cs-field__control", rows: "3" })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("button", { type: "submit", className: "btn-gold" }, t.form.submit, /* @__PURE__ */ React.createElement(I, { name: "arrow-right", size: 18 }))))))), /* @__PURE__ */ React.createElement("footer", { className: "ft" }, /* @__PURE__ */ React.createElement("div", { className: "container ft-in" }, /* @__PURE__ */ React.createElement("a", { className: "brand", href: "#top" }, /* @__PURE__ */ React.createElement("img", { src: "../../assets/logo-mark.svg", alt: "" }), "CyberSkill"), /* @__PURE__ */ React.createElement("div", { className: "ft-links" }, t.footerLinks.map((l) => /* @__PURE__ */ React.createElement("a", { key: l, href: "#top" }, l))), /* @__PURE__ */ React.createElement("small", null, "© 2026 CyberSkill · ", t.footerRights, " · Saigon"))), !chat && /* @__PURE__ */ React.createElement(
|
|
5899
|
+
"button",
|
|
5900
|
+
{
|
|
5901
|
+
className: "fab",
|
|
5902
|
+
type: "button",
|
|
5903
|
+
"data-fab-deferred": "1",
|
|
5904
|
+
onClick: () => openChat(""),
|
|
5905
|
+
style: { opacity: fabVisible ? 1 : 0, pointerEvents: fabVisible ? "auto" : "none", transition: "opacity 160ms ease" },
|
|
5906
|
+
"aria-hidden": !fabVisible,
|
|
5907
|
+
tabIndex: fabVisible ? 0 : -1
|
|
5908
|
+
},
|
|
5909
|
+
/* @__PURE__ */ React.createElement("img", { src: "../../assets/lumi-poster.webp", alt: "" }),
|
|
5910
|
+
t.talk
|
|
5911
|
+
), chat && /* @__PURE__ */ React.createElement(Chat, { t, seed, onClose: () => setChat(false) }));
|
|
5511
5912
|
}
|
|
5512
5913
|
window.Website = Website;
|
|
5513
5914
|
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/website/Website.jsx", error: String((e && e.message) || e) }); }
|
|
@@ -5824,6 +6225,8 @@ __ds_ns.Drawer = __ds_scope.Drawer;
|
|
|
5824
6225
|
|
|
5825
6226
|
__ds_ns.HoverCard = __ds_scope.HoverCard;
|
|
5826
6227
|
|
|
6228
|
+
__ds_ns.OverlayProvider = __ds_scope.OverlayProvider;
|
|
6229
|
+
|
|
5827
6230
|
__ds_ns.Popconfirm = __ds_scope.Popconfirm;
|
|
5828
6231
|
|
|
5829
6232
|
__ds_ns.Popover = __ds_scope.Popover;
|