@geenius/feedback 0.1.0 → 0.3.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/package.json +16 -3
- package/packages/convex/dist/index.d.ts +192 -0
- package/packages/convex/dist/index.js +239 -0
- package/packages/convex/dist/index.js.map +1 -0
- package/packages/react/README.md +1 -1
- package/packages/react/dist/index.d.ts +146 -0
- package/packages/react/dist/index.js +545 -0
- package/packages/react/dist/index.js.map +1 -0
- package/packages/react-css/README.md +1 -1
- package/packages/react-css/dist/index.css +965 -0
- package/packages/react-css/dist/index.css.map +1 -0
- package/packages/react-css/dist/index.d.ts +49 -0
- package/packages/react-css/dist/index.js +228 -0
- package/packages/react-css/dist/index.js.map +1 -0
- package/packages/shared/README.md +1 -1
- package/packages/shared/dist/index.d.ts +115 -0
- package/packages/shared/dist/index.js +112 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/packages/solidjs/README.md +1 -1
- package/packages/solidjs/dist/index.d.ts +128 -0
- package/packages/solidjs/dist/index.js +289 -0
- package/packages/solidjs/dist/index.js.map +1 -0
- package/packages/solidjs-css/README.md +1 -1
- package/packages/solidjs-css/dist/index.css +965 -0
- package/packages/solidjs-css/dist/index.css.map +1 -0
- package/packages/solidjs-css/dist/index.d.ts +2 -0
- package/packages/solidjs-css/dist/index.js +29 -0
- package/packages/solidjs-css/dist/index.js.map +1 -0
- package/.changeset/config.json +0 -11
- package/.github/CODEOWNERS +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -23
- package/.github/workflows/release.yml +0 -29
- package/.nvmrc +0 -1
- package/.project/ACCOUNT.yaml +0 -4
- package/.project/IDEAS.yaml +0 -7
- package/.project/PROJECT.yaml +0 -11
- package/.project/ROADMAP.yaml +0 -15
- package/CODE_OF_CONDUCT.md +0 -16
- package/CONTRIBUTING.md +0 -26
- package/SECURITY.md +0 -15
- package/SUPPORT.md +0 -8
- package/packages/convex/package.json +0 -42
- package/packages/convex/src/index.ts +0 -3
- package/packages/convex/src/mutations.ts +0 -88
- package/packages/convex/src/queries.ts +0 -78
- package/packages/convex/src/schema.ts +0 -47
- package/packages/convex/tsconfig.json +0 -18
- package/packages/convex/tsup.config.ts +0 -17
- package/packages/react/package.json +0 -49
- package/packages/react/src/components/FeedbackCard.tsx +0 -51
- package/packages/react/src/components/FeedbackForm.tsx +0 -43
- package/packages/react/src/components/FeedbackWidget.tsx +0 -32
- package/packages/react/src/components/NPSSurvey.tsx +0 -62
- package/packages/react/src/components/index.ts +0 -4
- package/packages/react/src/hooks/index.ts +0 -5
- package/packages/react/src/hooks/useFeedback.ts +0 -23
- package/packages/react/src/hooks/useFeedbackAdmin.ts +0 -24
- package/packages/react/src/hooks/useFeedbackForm.ts +0 -35
- package/packages/react/src/hooks/useNPS.ts +0 -26
- package/packages/react/src/index.tsx +0 -13
- package/packages/react/src/pages/FeedbackAdminPage.tsx +0 -71
- package/packages/react/src/pages/FeedbackPublicPage.tsx +0 -42
- package/packages/react/src/pages/FeedbackWidgetPage.tsx +0 -25
- package/packages/react/src/pages/index.ts +0 -3
- package/packages/react/tsconfig.json +0 -19
- package/packages/react/tsup.config.ts +0 -12
- package/packages/react-css/package.json +0 -36
- package/packages/react-css/src/components/index.ts +0 -5
- package/packages/react-css/src/components/index.tsx +0 -107
- package/packages/react-css/src/hooks/index.ts +0 -2
- package/packages/react-css/src/index.tsx +0 -5
- package/packages/react-css/src/pages/FeedbackAdminPage.tsx +0 -112
- package/packages/react-css/src/pages/FeedbackPage.tsx +0 -76
- package/packages/react-css/src/styles.css +0 -281
- package/packages/react-css/tsconfig.json +0 -19
- package/packages/react-css/tsup.config.ts +0 -10
- package/packages/shared/package.json +0 -44
- package/packages/shared/src/__tests__/feedback.test.ts +0 -72
- package/packages/shared/src/config.ts +0 -49
- package/packages/shared/src/index.ts +0 -111
- package/packages/shared/src/types.ts +0 -59
- package/packages/shared/tsconfig.json +0 -18
- package/packages/shared/tsup.config.ts +0 -11
- package/packages/shared/vitest.config.ts +0 -4
- package/packages/solidjs/package.json +0 -45
- package/packages/solidjs/src/components.tsx +0 -72
- package/packages/solidjs/src/index.tsx +0 -3
- package/packages/solidjs/src/primitives.ts +0 -49
- package/packages/solidjs/tsconfig.json +0 -20
- package/packages/solidjs/tsup.config.ts +0 -12
- package/packages/solidjs-css/package.json +0 -32
- package/packages/solidjs-css/src/index.tsx +0 -4
- package/packages/solidjs-css/src/pages/FeedbackAdminPage.tsx +0 -78
- package/packages/solidjs-css/src/pages/FeedbackPage.tsx +0 -65
- package/packages/solidjs-css/src/primitives/index.ts +0 -1
- package/packages/solidjs-css/src/styles.css +0 -281
- package/packages/solidjs-css/tsconfig.json +0 -20
- package/packages/solidjs-css/tsup.config.ts +0 -10
- package/pnpm-workspace.yaml +0 -2
- package/tsconfig.json +0 -23
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/styles.css"],"sourcesContent":["/* ─── Feedback Design Tokens (OKLCH) ──────────────────── */\n:root {\n --feedback-bg: oklch(0.12 0.01 250);\n --feedback-surface: oklch(0.16 0.01 250);\n --feedback-border: oklch(0.22 0.01 250);\n --feedback-text: oklch(0.95 0.01 250);\n --feedback-text-muted: oklch(0.58 0.02 250);\n --feedback-accent: oklch(0.65 0.20 265);\n --feedback-open: oklch(0.65 0.20 245);\n --feedback-review: oklch(0.72 0.18 60);\n --feedback-planned: oklch(0.70 0.22 280);\n --feedback-progress: oklch(0.65 0.20 265);\n --feedback-done: oklch(0.72 0.18 155);\n --feedback-declined: oklch(0.50 0.10 250);\n --feedback-bug: oklch(0.60 0.25 25);\n --feedback-feature: oklch(0.70 0.22 280);\n --feedback-suggestion: oklch(0.72 0.18 60);\n --feedback-general: oklch(0.65 0.20 245);\n --feedback-radius: 0.75rem;\n}\n\n/* ─── Feedback Card ──────────────────────────────────── */\n.feedback__card {\n display: flex;\n gap: 0.75rem;\n padding: 1rem;\n border: 1px solid var(--feedback-border);\n border-radius: var(--feedback-radius);\n background: oklch(1 0 0 / 0.02);\n transition: all 0.2s;\n cursor: pointer;\n}\n.feedback__card:hover { border-color: oklch(0.65 0.20 265 / 0.2); background: oklch(1 0 0 / 0.04); }\n.feedback__card-info { flex: 1; min-width: 0; }\n.feedback__card-badges { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.25rem; }\n.feedback__card-title { font-size: 0.875rem; font-weight: 600; color: oklch(1 0 0 / 0.9); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-bottom: 0.125rem; }\n.feedback__card-desc { font-size: 0.6875rem; color: oklch(1 0 0 / 0.4); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\n.feedback__card-meta { display: flex; align-items: center; gap: 0.75rem; margin-top: 0.5rem; font-size: 0.625rem; color: oklch(1 0 0 / 0.25); }\n.feedback__card--bug { border-left: 3px solid var(--feedback-bug); }\n.feedback__card--feature { border-left: 3px solid var(--feedback-feature); }\n.feedback__card--suggestion { border-left: 3px solid var(--feedback-suggestion); }\n.feedback__card--general { border-left: 3px solid var(--feedback-general); }\n\n/* ─── Vote Button ────────────────────────────────────── */\n.feedback__vote-btn {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.125rem;\n padding: 0.375rem 0.5rem;\n border-radius: calc(var(--feedback-radius) * 0.8);\n border: none;\n font-size: 0.6875rem;\n font-weight: 700;\n cursor: pointer;\n transition: all 0.15s;\n font-variant-numeric: tabular-nums;\n}\n.feedback__vote-btn--inactive { background: oklch(1 0 0 / 0.05); color: oklch(1 0 0 / 0.3); }\n.feedback__vote-btn--inactive:hover { background: oklch(1 0 0 / 0.1); color: oklch(1 0 0 / 0.5); }\n.feedback__vote-btn--active { background: oklch(0.65 0.20 265 / 0.15); color: oklch(0.65 0.20 265); }\n.feedback__vote-btn-arrow { font-size: 0.875rem; }\n\n/* ─── Status Badge ───────────────────────────────────── */\n.feedback__status-badge { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.125rem 0.625rem; border-radius: 9999px; font-size: 0.625rem; font-weight: 500; }\n.feedback__status-badge--open { background: oklch(0.65 0.20 245 / 0.15); color: oklch(0.65 0.20 245); }\n.feedback__status-badge--under-review { background: oklch(0.72 0.18 60 / 0.15); color: oklch(0.72 0.18 60); }\n.feedback__status-badge--planned { background: oklch(0.70 0.22 280 / 0.15); color: oklch(0.70 0.22 280); }\n.feedback__status-badge--in-progress { background: oklch(0.65 0.20 265 / 0.15); color: oklch(0.65 0.20 265); }\n.feedback__status-badge--done { background: oklch(0.72 0.18 155 / 0.15); color: oklch(0.72 0.18 155); }\n.feedback__status-badge--declined { background: oklch(0.50 0.10 250 / 0.15); color: oklch(0.50 0.10 250); }\n\n/* ─── Priority Badge ─────────────────────────────────── */\n.feedback__priority-badge { padding: 0.125rem 0.5rem; border-radius: 9999px; font-size: 0.625rem; font-weight: 500; }\n.feedback__priority-badge--low { background: oklch(0.58 0.10 250 / 0.15); color: oklch(0.58 0.10 250); }\n.feedback__priority-badge--medium { background: oklch(0.72 0.18 60 / 0.15); color: oklch(0.72 0.18 60); }\n.feedback__priority-badge--high { background: oklch(0.68 0.22 35 / 0.15); color: oklch(0.68 0.22 35); }\n.feedback__priority-badge--critical { background: oklch(0.60 0.25 25 / 0.15); color: oklch(0.60 0.25 25); }\n\n/* ─── Type Badge ─────────────────────────────────────── */\n.feedback__type-badge { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.125rem 0.5rem; border-radius: 9999px; font-size: 0.625rem; font-weight: 500; }\n.feedback__type-badge--bug { background: oklch(0.60 0.25 25 / 0.15); color: oklch(0.60 0.25 25); }\n.feedback__type-badge--feature { background: oklch(0.70 0.22 280 / 0.15); color: oklch(0.70 0.22 280); }\n.feedback__type-badge--suggestion { background: oklch(0.72 0.18 60 / 0.15); color: oklch(0.72 0.18 60); }\n.feedback__type-badge--general { background: oklch(0.65 0.20 245 / 0.15); color: oklch(0.65 0.20 245); }\n\n/* ─── Widget ─────────────────────────────────────────── */\n.feedback__widget-trigger {\n position: fixed; top: 50%; right: 0; transform: translateY(-50%);\n z-index: 40; padding: 0.5rem 1rem; border-radius: var(--feedback-radius) 0 0 var(--feedback-radius);\n background: var(--feedback-accent); color: white; border: none; cursor: pointer;\n writing-mode: vertical-rl; font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.05em;\n box-shadow: -2px 0 12px oklch(0.65 0.20 265 / 0.3);\n}\n.feedback__widget-trigger:hover { background: oklch(0.70 0.22 265); }\n.feedback__widget-overlay { position: fixed; inset: 0; z-index: 50; display: flex; justify-content: flex-end; }\n.feedback__widget-backdrop { position: absolute; inset: 0; background: oklch(0 0 0 / 0.5); backdrop-filter: blur(4px); }\n.feedback__widget-panel { position: relative; width: 100%; max-width: 28rem; background: oklch(0.06 0.01 250); border-left: 1px solid var(--feedback-border); padding: 1.5rem; overflow-y: auto; }\n.feedback__widget-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.5rem; }\n.feedback__widget-title { font-size: 1.125rem; font-weight: 700; color: var(--feedback-text); }\n\n/* ─── Form ───────────────────────────────────────────── */\n.feedback__form { display: flex; flex-direction: column; gap: 1rem; }\n.feedback__form-input { width: 100%; padding: 0.75rem 1rem; border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.03); font-size: 0.875rem; color: var(--feedback-text); outline: none; }\n.feedback__form-input::placeholder { color: oklch(1 0 0 / 0.3); }\n.feedback__form-input:focus { border-color: oklch(0.65 0.20 265 / 0.4); }\n.feedback__form-textarea { resize: none; min-height: 6rem; }\n.feedback__form-error { font-size: 0.6875rem; color: oklch(0.60 0.25 25); }\n.feedback__form-actions { display: flex; justify-content: flex-end; gap: 0.5rem; }\n\n/* ─── Type Selector ──────────────────────────────────── */\n.feedback__type-selector { display: flex; gap: 0.375rem; }\n.feedback__type-tab { display: flex; align-items: center; gap: 0.375rem; padding: 0.5rem 0.75rem; border-radius: calc(var(--feedback-radius) * 0.8); border: none; font-size: 0.6875rem; font-weight: 500; cursor: pointer; transition: all 0.15s; }\n.feedback__type-tab--inactive { background: oklch(1 0 0 / 0.05); color: oklch(1 0 0 / 0.5); }\n.feedback__type-tab--inactive:hover { background: oklch(1 0 0 / 0.1); }\n\n/* ─── NPS ────────────────────────────────────────────── */\n.feedback__nps { position: fixed; bottom: 1.5rem; right: 1.5rem; z-index: 50; width: 24rem; border: 1px solid oklch(1 0 0 / 0.1); border-radius: calc(var(--feedback-radius) * 1.5); background: oklch(0.08 0.01 250); padding: 1.5rem; box-shadow: 0 8px 32px oklch(0 0 0 / 0.5); }\n.feedback__nps-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.25rem; }\n.feedback__nps-title { font-size: 0.875rem; font-weight: 600; color: oklch(1 0 0 / 0.9); }\n.feedback__nps-subtitle { font-size: 0.6875rem; color: oklch(1 0 0 / 0.4); margin-bottom: 1rem; }\n.feedback__nps-scores { display: flex; gap: 0.25rem; }\n.feedback__nps-score-btn { flex: 1; padding: 0.625rem 0; border: none; border-radius: calc(var(--feedback-radius) * 0.8); background: oklch(1 0 0 / 0.05); color: oklch(1 0 0 / 0.5); font-size: 0.6875rem; font-weight: 700; cursor: pointer; transition: all 0.15s; }\n.feedback__nps-score-btn:hover { background: oklch(1 0 0 / 0.1); }\n.feedback__nps-labels { display: flex; justify-content: space-between; margin-top: 0.5rem; font-size: 0.625rem; color: oklch(1 0 0 / 0.2); }\n.feedback__nps-results { padding: 1.25rem; border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.02); }\n.feedback__nps-results-score { font-size: 1.875rem; font-weight: 900; font-variant-numeric: tabular-nums; }\n.feedback__nps-bar { display: flex; height: 1.25rem; overflow: hidden; border-radius: 9999px; margin: 1rem 0; }\n.feedback__nps-bar-detractors { background: oklch(0.60 0.25 25 / 0.7); }\n.feedback__nps-bar-passives { background: oklch(0.72 0.18 60 / 0.7); }\n.feedback__nps-bar-promoters { background: oklch(0.72 0.18 155 / 0.7); }\n.feedback__nps-breakdown { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; text-align: center; font-size: 0.6875rem; }\n\n/* ─── Board ──────────────────────────────────────────── */\n.feedback__board { display: flex; flex-direction: column; gap: 0.625rem; }\n\n/* ─── Admin Table ────────────────────────────────────── */\n.feedback__admin-table { width: 100%; font-size: 0.875rem; border-collapse: collapse; }\n.feedback__admin-table th { padding: 0.75rem 1rem; text-align: left; font-size: 0.625rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: oklch(1 0 0 / 0.4); border-bottom: 1px solid oklch(1 0 0 / 0.08); }\n.feedback__admin-table td { padding: 0.75rem 1rem; border-bottom: 1px solid oklch(1 0 0 / 0.05); }\n.feedback__admin-table tr:hover { background: oklch(1 0 0 / 0.02); }\n.feedback__admin-select { padding: 0.25rem 0.5rem; border: 1px solid var(--feedback-border); border-radius: calc(var(--feedback-radius) * 0.6); background: oklch(1 0 0 / 0.05); font-size: 0.6875rem; color: var(--feedback-text); outline: none; }\n\n/* ─── Stats Grid ─────────────────────────────────────── */\n.feedback__stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1rem; margin-bottom: 2rem; }\n.feedback__stat-card { padding: 1rem; border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.02); }\n.feedback__stat-icon { font-size: 1.125rem; }\n.feedback__stat-value { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; color: oklch(1 0 0 / 0.9); }\n.feedback__stat-label { font-size: 0.6875rem; color: oklch(1 0 0 / 0.4); }\n\n/* ─── Search ─────────────────────────────────────────── */\n.feedback__search { width: 100%; max-width: 16rem; padding: 0.625rem 1rem; border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.03); font-size: 0.875rem; color: var(--feedback-text); outline: none; }\n.feedback__search::placeholder { color: oklch(1 0 0 / 0.3); }\n.feedback__search:focus { border-color: oklch(0.65 0.20 265 / 0.4); }\n\n/* ─── Filter Tabs ────────────────────────────────────── */\n.feedback__filter-tabs { display: flex; flex-wrap: wrap; gap: 0.375rem; }\n.feedback__filter-tab { padding: 0.375rem 0.75rem; border: none; border-radius: calc(var(--feedback-radius) * 0.8); font-size: 0.6875rem; font-weight: 500; cursor: pointer; }\n.feedback__filter-tab--active { background: var(--feedback-accent); color: white; }\n.feedback__filter-tab--inactive { background: oklch(1 0 0 / 0.05); color: oklch(1 0 0 / 0.5); }\n.feedback__filter-tab--inactive:hover { background: oklch(1 0 0 / 0.1); }\n\n/* ─── Btn ────────────────────────────────────────────── */\n.feedback__btn { padding: 0.5rem 1rem; border-radius: calc(var(--feedback-radius) * 0.8); font-size: 0.6875rem; font-weight: 500; cursor: pointer; border: none; transition: all 0.15s; }\n.feedback__btn--primary { background: var(--feedback-accent); color: white; }\n.feedback__btn--primary:hover { background: oklch(0.70 0.22 265); }\n.feedback__btn--outline { border: 1px solid var(--feedback-border); background: transparent; color: oklch(1 0 0 / 0.6); }\n.feedback__btn--danger { background: oklch(0.60 0.25 25 / 0.2); color: oklch(0.60 0.25 25); }\n\n/* ─── Skeleton ───────────────────────────────────────── */\n.feedback__skeleton { background: oklch(1 0 0 / 0.05); border-radius: var(--feedback-radius); animation: feedback-pulse 1.5s ease-in-out infinite; }\n@keyframes feedback-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }\n\n/* ─── Empty ──────────────────────────────────────────── */\n.feedback__empty { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 4rem 1rem; text-align: center; }\n.feedback__empty-icon { font-size: 3rem; opacity: 0.2; margin-bottom: 0.75rem; }\n.feedback__empty-text { font-size: 0.875rem; color: oklch(1 0 0 / 0.4); }\n\n/* ─── Success ────────────────────────────────────────── */\n.feedback__success { display: flex; flex-direction: column; align-items: center; padding: 2rem; text-align: center; }\n.feedback__success-icon { font-size: 2.5rem; margin-bottom: 0.75rem; }\n.feedback__success-text { font-size: 1rem; font-weight: 600; color: oklch(1 0 0 / 0.9); margin-bottom: 0.25rem; }\n.feedback__success-sub { font-size: 0.875rem; color: oklch(1 0 0 / 0.5); }\n\n/* ─── Tag ────────────────────────────────────────────── */\n.feedback__tag { padding: 0.125rem 0.375rem; border-radius: 0.25rem; background: oklch(1 0 0 / 0.05); font-size: 0.625rem; color: oklch(1 0 0 / 0.3); }\n\n/* ─── Close Button ───────────────────────────────────── */\n.feedback__close-btn { padding: 0.375rem; border: none; background: transparent; color: oklch(1 0 0 / 0.3); cursor: pointer; border-radius: calc(var(--feedback-radius) * 0.6); }\n.feedback__close-btn:hover { color: oklch(1 0 0 / 0.5); background: oklch(1 0 0 / 0.05); }\n\n/* ─── Comment Thread ─────────────────────────────────── */\n.feedback__comment-thread { display: flex; flex-direction: column; gap: 1rem; padding: 1rem; border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.01); }\n.feedback__comment { display: flex; gap: 0.75rem; }\n.feedback__comment-avatar { width: 2rem; height: 2rem; border-radius: 50%; background: oklch(0.65 0.20 265 / 0.2); display: flex; align-items: center; justify-content: center; font-size: 0.875rem; flex-shrink: 0; }\n.feedback__comment-body { flex: 1; }\n.feedback__comment-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.25rem; }\n.feedback__comment-author { font-size: 0.75rem; font-weight: 600; color: oklch(1 0 0 / 0.8); }\n.feedback__comment-time { font-size: 0.625rem; color: oklch(1 0 0 / 0.3); }\n.feedback__comment-text { font-size: 0.6875rem; color: oklch(1 0 0 / 0.7); line-height: 1.4; }\n.feedback__comment-reply-btn { margin-top: 0.5rem; padding: 0.25rem 0.5rem; font-size: 0.625rem; border: none; background: transparent; color: oklch(0.65 0.20 265); cursor: pointer; transition: all 0.1s; }\n.feedback__comment-reply-btn:hover { color: oklch(0.70 0.22 265); }\n\n/* ─── Rating Component ───────────────────────────────── */\n.feedback__rating { display: flex; gap: 0.25rem; }\n.feedback__rating-star { font-size: 1.5rem; cursor: pointer; opacity: 0.3; transition: all 0.15s; }\n.feedback__rating-star--filled { opacity: 1; color: oklch(0.72 0.18 60); }\n.feedback__rating-star:hover { opacity: 1; transform: scale(1.1); }\n\n/* ─── Sentiment Indicator ────────────────────────────── */\n.feedback__sentiment-card { padding: 1rem; border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.02); text-align: center; }\n.feedback__sentiment-icon { font-size: 2rem; margin-bottom: 0.5rem; }\n.feedback__sentiment-label { font-size: 0.875rem; font-weight: 600; color: oklch(1 0 0 / 0.8); margin-bottom: 0.25rem; }\n.feedback__sentiment-count { font-size: 0.6875rem; color: oklch(1 0 0 / 0.4); }\n\n/* ─── Response Panel ─────────────────────────────────── */\n.feedback__response-panel { border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.02); padding: 1rem; }\n.feedback__response-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.75rem; }\n.feedback__response-title { font-size: 0.875rem; font-weight: 600; color: oklch(1 0 0 / 0.8); }\n.feedback__response-time { font-size: 0.625rem; color: oklch(1 0 0 / 0.3); }\n.feedback__response-body { font-size: 0.6875rem; color: oklch(1 0 0 / 0.7); line-height: 1.5; }\n.feedback__response-actions { display: flex; gap: 0.5rem; margin-top: 0.75rem; }\n.feedback__response-btn { padding: 0.25rem 0.5rem; font-size: 0.625rem; border: none; background: oklch(1 0 0 / 0.05); color: oklch(1 0 0 / 0.5); cursor: pointer; border-radius: calc(var(--feedback-radius) * 0.6); transition: all 0.1s; }\n.feedback__response-btn:hover { background: oklch(1 0 0 / 0.1); color: oklch(1 0 0 / 0.6); }\n\n/* ─── Analytics Chart ────────────────────────────────── */\n.feedback__analytics { border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.02); padding: 1rem; }\n.feedback__analytics-title { font-size: 0.875rem; font-weight: 600; color: oklch(1 0 0 / 0.8); margin-bottom: 1rem; }\n.feedback__analytics-chart { display: flex; align-items: flex-end; gap: 0.5rem; height: 10rem; }\n.feedback__analytics-bar { flex: 1; border-radius: 0.25rem 0.25rem 0 0; background: linear-gradient(to top, oklch(0.65 0.20 265), oklch(0.65 0.20 265 / 0.4)); transition: all 0.2s; position: relative; }\n.feedback__analytics-bar:hover { background: linear-gradient(to top, oklch(0.70 0.22 265), oklch(0.70 0.22 265)); }\n.feedback__analytics-label { position: absolute; bottom: -1.5rem; left: 50%; transform: translateX(-50%); font-size: 0.625rem; color: oklch(1 0 0 / 0.4); white-space: nowrap; }\n\n/* ─── Filter Control Panel ───────────────────────────── */\n.feedback__filter-panel { border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.02); padding: 1rem; }\n.feedback__filter-section { margin-bottom: 1rem; }\n.feedback__filter-section:last-child { margin-bottom: 0; }\n.feedback__filter-section-title { font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; color: oklch(1 0 0 / 0.4); margin-bottom: 0.5rem; letter-spacing: 0.05em; }\n.feedback__filter-options { display: flex; flex-direction: column; gap: 0.25rem; }\n.feedback__filter-option { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0; font-size: 0.6875rem; }\n.feedback__filter-option input { cursor: pointer; }\n.feedback__filter-option-label { color: oklch(1 0 0 / 0.7); cursor: pointer; }\n\n/* ─── Tag Selector ───────────────────────────────────── */\n.feedback__tag-selector { padding: 1rem; border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.02); }\n.feedback__tag-selector-label { display: block; font-size: 0.6875rem; font-weight: 500; color: oklch(1 0 0 / 0.6); margin-bottom: 0.5rem; text-transform: uppercase; }\n.feedback__tag-list { display: flex; flex-wrap: wrap; gap: 0.5rem; }\n.feedback__tag-item { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.375rem 0.75rem; border-radius: 9999px; background: oklch(0.65 0.20 265 / 0.15); color: oklch(0.65 0.20 265); font-size: 0.6875rem; font-weight: 500; }\n.feedback__tag-remove { margin-left: 0.25rem; cursor: pointer; font-weight: 700; opacity: 0.6; transition: opacity 0.1s; }\n.feedback__tag-remove:hover { opacity: 1; }\n\n/* ─── Feedback Form Actions ──────────────────────────── */\n.feedback__form-footer { display: flex; justify-content: space-between; align-items: center; padding-top: 1rem; border-top: 1px solid var(--feedback-border); }\n.feedback__form-counter { font-size: 0.625rem; color: oklch(1 0 0 / 0.3); }\n.feedback__form-actions-group { display: flex; gap: 0.5rem; }\n\n/* ─── Feedback Status Indicator ──────────────────────── */\n.feedback__status-indicator { display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.75rem; border-radius: 9999px; font-size: 0.625rem; font-weight: 500; }\n.feedback__status-indicator--new { background: oklch(0.65 0.20 245 / 0.15); color: oklch(0.65 0.20 245); }\n.feedback__status-indicator--in-review { background: oklch(0.72 0.18 60 / 0.15); color: oklch(0.72 0.18 60); }\n.feedback__status-indicator--implemented { background: oklch(0.72 0.18 155 / 0.15); color: oklch(0.72 0.18 155); }\n\n/* ─── Detailed Stats Row ─────────────────────────────── */\n.feedback__detailed-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 0.5rem; }\n.feedback__detailed-stat-item { padding: 0.75rem; border: 1px solid var(--feedback-border); border-radius: var(--feedback-radius); background: oklch(1 0 0 / 0.01); text-align: center; }\n.feedback__detailed-stat-icon { font-size: 1.25rem; margin-bottom: 0.25rem; }\n.feedback__detailed-stat-value { font-size: 1rem; font-weight: 700; color: oklch(1 0 0 / 0.9); }\n.feedback__detailed-stat-label { font-size: 0.625rem; color: oklch(1 0 0 / 0.4); margin-top: 0.25rem; }\n\n/* ─── Breadcrumb Navigation ──────────────────────────── */\n.feedback__breadcrumb { display: flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; margin-bottom: 1rem; }\n.feedback__breadcrumb-item { color: oklch(1 0 0 / 0.5); }\n.feedback__breadcrumb-item--active { color: oklch(1 0 0 / 0.8); font-weight: 500; }\n.feedback__breadcrumb-sep { color: oklch(1 0 0 / 0.2); margin: 0 0.25rem; }\n\n/* ─── Pagination Controls ────────────────────────────── */\n.feedback__pagination { display: flex; align-items: center; gap: 0.5rem; justify-content: center; padding: 1rem; }\n.feedback__pagination-btn { padding: 0.375rem 0.75rem; border: 1px solid var(--feedback-border); border-radius: calc(var(--feedback-radius) * 0.6); background: oklch(1 0 0 / 0.05); color: oklch(1 0 0 / 0.6); font-size: 0.6875rem; cursor: pointer; transition: all 0.1s; }\n.feedback__pagination-btn:hover:not(:disabled) { background: oklch(1 0 0 / 0.1); color: oklch(1 0 0 / 0.8); }\n.feedback__pagination-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n.feedback__pagination-info { font-size: 0.6875rem; color: oklch(1 0 0 / 0.5); }\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export { FeedbackFilter, FeedbackProvider, useFeedback, useFeedbackAdmin, useFeedbackConfig, useFeedbackForm, useNPS } from '@geenius/feedback-react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { FeedbackItem, FeedbackType, NPSResponse, FeedbackPriority, FeedbackStatus } from '@geenius/feedback-shared';
|
|
4
|
+
export { FeedbackConfig, FeedbackItem, FeedbackPriority, FeedbackStats, FeedbackStatus, FeedbackType, NPSResponse, NPSStats } from '@geenius/feedback-shared';
|
|
5
|
+
|
|
6
|
+
declare function StatusBadge({ status }: {
|
|
7
|
+
status: FeedbackStatus;
|
|
8
|
+
}): react_jsx_runtime.JSX.Element;
|
|
9
|
+
declare function PriorityBadge({ priority }: {
|
|
10
|
+
priority: FeedbackPriority;
|
|
11
|
+
}): react_jsx_runtime.JSX.Element;
|
|
12
|
+
declare function TypeBadge({ type }: {
|
|
13
|
+
type: FeedbackType;
|
|
14
|
+
}): react_jsx_runtime.JSX.Element;
|
|
15
|
+
declare function FeedbackCard({ item, onVote, hasVoted, onClick }: {
|
|
16
|
+
item: FeedbackItem;
|
|
17
|
+
onVote?: (id: string) => void;
|
|
18
|
+
hasVoted?: boolean;
|
|
19
|
+
onClick?: (id: string) => void;
|
|
20
|
+
}): react_jsx_runtime.JSX.Element;
|
|
21
|
+
declare function FeedbackTypeSelector({ value, onChange }: {
|
|
22
|
+
value: FeedbackType;
|
|
23
|
+
onChange: (t: FeedbackType) => void;
|
|
24
|
+
}): react_jsx_runtime.JSX.Element;
|
|
25
|
+
declare function FeedbackForm({ onSubmit, onClose }: {
|
|
26
|
+
onSubmit: (data: {
|
|
27
|
+
type: FeedbackType;
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
}) => Promise<string>;
|
|
31
|
+
onClose?: () => void;
|
|
32
|
+
}): react_jsx_runtime.JSX.Element;
|
|
33
|
+
declare function FeedbackWidget({ onSubmit, position }: {
|
|
34
|
+
onSubmit: (data: {
|
|
35
|
+
type: FeedbackType;
|
|
36
|
+
title: string;
|
|
37
|
+
description: string;
|
|
38
|
+
}) => Promise<string>;
|
|
39
|
+
position?: 'left' | 'right';
|
|
40
|
+
}): react_jsx_runtime.JSX.Element;
|
|
41
|
+
declare function NPSSurvey({ onSubmit, onDismiss }: {
|
|
42
|
+
onSubmit: (score: number, comment?: string) => void;
|
|
43
|
+
onDismiss: () => void;
|
|
44
|
+
}): react_jsx_runtime.JSX.Element;
|
|
45
|
+
declare function NPSResults({ responses }: {
|
|
46
|
+
responses: NPSResponse[];
|
|
47
|
+
}): react_jsx_runtime.JSX.Element;
|
|
48
|
+
|
|
49
|
+
export { FeedbackCard, FeedbackForm, FeedbackTypeSelector, FeedbackWidget, NPSResults, NPSSurvey, PriorityBadge, StatusBadge, TypeBadge };
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
// src/index.tsx
|
|
2
|
+
import { FeedbackProvider, useFeedbackConfig } from "@geenius/feedback-react";
|
|
3
|
+
|
|
4
|
+
// src/hooks/index.ts
|
|
5
|
+
import { useFeedback, useFeedbackForm, useNPS, useFeedbackAdmin } from "@geenius/feedback-react";
|
|
6
|
+
|
|
7
|
+
// src/components/index.tsx
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { STATUS_CONFIG, PRIORITY_CONFIG, TYPE_CONFIG, FEEDBACK_TYPES, formatRelativeTime, calcNPSStats } from "@geenius/feedback-shared";
|
|
10
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
function StatusBadge({ status }) {
|
|
12
|
+
return /* @__PURE__ */ jsxs("span", { className: `feedback__status-badge feedback__status-badge--${status}`, children: [
|
|
13
|
+
STATUS_CONFIG[status].emoji,
|
|
14
|
+
" ",
|
|
15
|
+
STATUS_CONFIG[status].label
|
|
16
|
+
] });
|
|
17
|
+
}
|
|
18
|
+
function PriorityBadge({ priority }) {
|
|
19
|
+
return /* @__PURE__ */ jsx("span", { className: `feedback__priority-badge feedback__priority-badge--${priority}`, children: PRIORITY_CONFIG[priority].label });
|
|
20
|
+
}
|
|
21
|
+
function TypeBadge({ type }) {
|
|
22
|
+
return /* @__PURE__ */ jsxs("span", { className: `feedback__type-badge feedback__type-badge--${type}`, children: [
|
|
23
|
+
TYPE_CONFIG[type].icon,
|
|
24
|
+
" ",
|
|
25
|
+
TYPE_CONFIG[type].label
|
|
26
|
+
] });
|
|
27
|
+
}
|
|
28
|
+
function FeedbackCard({ item, onVote, hasVoted, onClick }) {
|
|
29
|
+
return /* @__PURE__ */ jsxs("div", { className: `feedback__card feedback__card--${item.type}`, onClick: () => onClick?.(item.id), children: [
|
|
30
|
+
onVote && /* @__PURE__ */ jsxs("button", { type: "button", className: `feedback__vote-btn ${hasVoted ? "feedback__vote-btn--active" : "feedback__vote-btn--inactive"}`, onClick: (e) => {
|
|
31
|
+
e.stopPropagation();
|
|
32
|
+
onVote(item.id);
|
|
33
|
+
}, children: [
|
|
34
|
+
/* @__PURE__ */ jsx("span", { className: "feedback__vote-btn-arrow", children: hasVoted ? "\u25B2" : "\u25B3" }),
|
|
35
|
+
/* @__PURE__ */ jsx("span", { children: item.votes })
|
|
36
|
+
] }),
|
|
37
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__card-info", children: [
|
|
38
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__card-badges", children: [
|
|
39
|
+
/* @__PURE__ */ jsx(TypeBadge, { type: item.type }),
|
|
40
|
+
/* @__PURE__ */ jsx(StatusBadge, { status: item.status }),
|
|
41
|
+
/* @__PURE__ */ jsx(PriorityBadge, { priority: item.priority })
|
|
42
|
+
] }),
|
|
43
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__card-title", children: item.title }),
|
|
44
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__card-desc", children: item.description }),
|
|
45
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__card-meta", children: [
|
|
46
|
+
item.userName && /* @__PURE__ */ jsx("span", { children: item.userName }),
|
|
47
|
+
/* @__PURE__ */ jsx("span", { children: formatRelativeTime(item.createdAt) }),
|
|
48
|
+
item.tags.map((t) => /* @__PURE__ */ jsx("span", { className: "feedback__tag", children: t }, t))
|
|
49
|
+
] })
|
|
50
|
+
] })
|
|
51
|
+
] });
|
|
52
|
+
}
|
|
53
|
+
function FeedbackTypeSelector({ value, onChange }) {
|
|
54
|
+
return /* @__PURE__ */ jsx("div", { className: "feedback__type-selector", children: FEEDBACK_TYPES.map((t) => /* @__PURE__ */ jsxs(
|
|
55
|
+
"button",
|
|
56
|
+
{
|
|
57
|
+
type: "button",
|
|
58
|
+
onClick: () => onChange(t),
|
|
59
|
+
className: `feedback__type-tab ${value === t ? "" : "feedback__type-tab--inactive"}`,
|
|
60
|
+
style: value === t ? { background: TYPE_CONFIG[t].color, color: "white" } : void 0,
|
|
61
|
+
children: [
|
|
62
|
+
TYPE_CONFIG[t].icon,
|
|
63
|
+
" ",
|
|
64
|
+
TYPE_CONFIG[t].label
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
t
|
|
68
|
+
)) });
|
|
69
|
+
}
|
|
70
|
+
function FeedbackForm({ onSubmit, onClose }) {
|
|
71
|
+
const [type, setType] = useState("general");
|
|
72
|
+
const [title, setTitle] = useState("");
|
|
73
|
+
const [desc, setDesc] = useState("");
|
|
74
|
+
const [submitting, setSubmitting] = useState(false);
|
|
75
|
+
const [error, setError] = useState(null);
|
|
76
|
+
const [success, setSuccess] = useState(false);
|
|
77
|
+
const submit = async () => {
|
|
78
|
+
if (!title.trim()) {
|
|
79
|
+
setError("Title required");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
;
|
|
83
|
+
if (desc.length < 10) {
|
|
84
|
+
setError("10+ chars");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
setSubmitting(true);
|
|
88
|
+
setError(null);
|
|
89
|
+
try {
|
|
90
|
+
await onSubmit({ type, title, description: desc });
|
|
91
|
+
setSuccess(true);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
setError(String(e));
|
|
94
|
+
} finally {
|
|
95
|
+
setSubmitting(false);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
if (success) return /* @__PURE__ */ jsxs("div", { className: "feedback__success", children: [
|
|
99
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__success-icon", children: "\u{1F389}" }),
|
|
100
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__success-text", children: "Thank you!" }),
|
|
101
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__success-sub", children: "Feedback submitted" })
|
|
102
|
+
] });
|
|
103
|
+
return /* @__PURE__ */ jsxs("div", { className: "feedback__form", children: [
|
|
104
|
+
/* @__PURE__ */ jsx(FeedbackTypeSelector, { value: type, onChange: setType }),
|
|
105
|
+
/* @__PURE__ */ jsx("input", { type: "text", className: "feedback__form-input", placeholder: "Title\u2026", value: title, onChange: (e) => setTitle(e.target.value) }),
|
|
106
|
+
/* @__PURE__ */ jsx("textarea", { className: "feedback__form-input feedback__form-textarea", placeholder: "Description\u2026", value: desc, onChange: (e) => setDesc(e.target.value) }),
|
|
107
|
+
error && /* @__PURE__ */ jsx("div", { className: "feedback__form-error", children: error }),
|
|
108
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__form-actions", children: [
|
|
109
|
+
onClose && /* @__PURE__ */ jsx("button", { type: "button", className: "feedback__btn feedback__btn--outline", onClick: onClose, children: "Cancel" }),
|
|
110
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "feedback__btn feedback__btn--primary", onClick: submit, disabled: submitting, children: submitting ? "Submitting\u2026" : "Submit" })
|
|
111
|
+
] })
|
|
112
|
+
] });
|
|
113
|
+
}
|
|
114
|
+
function FeedbackWidget({ onSubmit, position = "right" }) {
|
|
115
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
116
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
117
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "feedback__widget-trigger", onClick: () => setIsOpen(true), children: "Feedback" }),
|
|
118
|
+
isOpen && /* @__PURE__ */ jsxs("div", { className: "feedback__widget-overlay", onClick: () => setIsOpen(false), children: [
|
|
119
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__widget-backdrop" }),
|
|
120
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__widget-panel", onClick: (e) => e.stopPropagation(), children: [
|
|
121
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__widget-header", children: [
|
|
122
|
+
/* @__PURE__ */ jsx("span", { className: "feedback__widget-title", children: "Send Feedback" }),
|
|
123
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "feedback__close-btn", onClick: () => setIsOpen(false), children: "\u2715" })
|
|
124
|
+
] }),
|
|
125
|
+
/* @__PURE__ */ jsx(FeedbackForm, { onSubmit, onClose: () => setIsOpen(false) })
|
|
126
|
+
] })
|
|
127
|
+
] })
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
function NPSSurvey({ onSubmit, onDismiss }) {
|
|
131
|
+
const [score, setScore] = useState(null);
|
|
132
|
+
const [comment, setComment] = useState("");
|
|
133
|
+
const [step, setStep] = useState("score");
|
|
134
|
+
return /* @__PURE__ */ jsxs("div", { className: "feedback__nps", children: [
|
|
135
|
+
step === "score" && /* @__PURE__ */ jsxs("div", { children: [
|
|
136
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__nps-header", children: [
|
|
137
|
+
/* @__PURE__ */ jsx("span", { className: "feedback__nps-title", children: "How likely to recommend us?" }),
|
|
138
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "feedback__close-btn", onClick: onDismiss, children: "\u2715" })
|
|
139
|
+
] }),
|
|
140
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__nps-subtitle", children: "0 = Not at all \xB7 10 = Extremely likely" }),
|
|
141
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__nps-scores", children: Array.from({ length: 11 }).map((_, i) => /* @__PURE__ */ jsx("button", { type: "button", className: "feedback__nps-score-btn", onClick: () => {
|
|
142
|
+
setScore(i);
|
|
143
|
+
setStep("comment");
|
|
144
|
+
}, children: i }, i)) }),
|
|
145
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__nps-labels", children: [
|
|
146
|
+
/* @__PURE__ */ jsx("span", { children: "Not likely" }),
|
|
147
|
+
/* @__PURE__ */ jsx("span", { children: "Very likely" })
|
|
148
|
+
] })
|
|
149
|
+
] }),
|
|
150
|
+
step === "comment" && /* @__PURE__ */ jsxs("div", { children: [
|
|
151
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__nps-title", style: { marginBottom: "0.75rem" }, children: [
|
|
152
|
+
"Score: ",
|
|
153
|
+
score
|
|
154
|
+
] }),
|
|
155
|
+
/* @__PURE__ */ jsx("textarea", { className: "feedback__form-input feedback__form-textarea", value: comment, onChange: (e) => setComment(e.target.value), placeholder: "Optional\u2026" }),
|
|
156
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "feedback__btn feedback__btn--primary", style: { width: "100%", marginTop: "0.75rem" }, onClick: () => {
|
|
157
|
+
onSubmit(score, comment || void 0);
|
|
158
|
+
setStep("thanks");
|
|
159
|
+
}, children: "Submit" })
|
|
160
|
+
] }),
|
|
161
|
+
step === "thanks" && /* @__PURE__ */ jsxs("div", { className: "feedback__success", children: [
|
|
162
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__success-icon", children: "\u{1F389}" }),
|
|
163
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__success-text", children: "Thank you!" })
|
|
164
|
+
] })
|
|
165
|
+
] });
|
|
166
|
+
}
|
|
167
|
+
function NPSResults({ responses }) {
|
|
168
|
+
const stats = calcNPSStats(responses);
|
|
169
|
+
const total = stats.totalResponses || 1;
|
|
170
|
+
const color = stats.npsScore >= 50 ? "oklch(0.72 0.18 155)" : stats.npsScore >= 0 ? "oklch(0.72 0.18 60)" : "oklch(0.60 0.25 25)";
|
|
171
|
+
return /* @__PURE__ */ jsxs("div", { className: "feedback__nps-results", children: [
|
|
172
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "0.5rem" }, children: [
|
|
173
|
+
/* @__PURE__ */ jsx("span", { children: "NPS Score" }),
|
|
174
|
+
/* @__PURE__ */ jsx("span", { className: "feedback__nps-results-score", style: { color }, children: stats.npsScore })
|
|
175
|
+
] }),
|
|
176
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__nps-bar", children: [
|
|
177
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__nps-bar-detractors", style: { width: `${stats.detractors / total * 100}%` } }),
|
|
178
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__nps-bar-passives", style: { width: `${stats.passives / total * 100}%` } }),
|
|
179
|
+
/* @__PURE__ */ jsx("div", { className: "feedback__nps-bar-promoters", style: { width: `${stats.promoters / total * 100}%` } })
|
|
180
|
+
] }),
|
|
181
|
+
/* @__PURE__ */ jsxs("div", { className: "feedback__nps-breakdown", children: [
|
|
182
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
183
|
+
/* @__PURE__ */ jsx("span", { style: { color: "oklch(0.60 0.25 25)", fontWeight: 700 }, children: stats.detractors }),
|
|
184
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
185
|
+
/* @__PURE__ */ jsx("span", { style: { color: "oklch(1 0 0/0.3)" }, children: "Detractors" })
|
|
186
|
+
] }),
|
|
187
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
188
|
+
/* @__PURE__ */ jsx("span", { style: { color: "oklch(0.72 0.18 60)", fontWeight: 700 }, children: stats.passives }),
|
|
189
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
190
|
+
/* @__PURE__ */ jsx("span", { style: { color: "oklch(1 0 0/0.3)" }, children: "Passives" })
|
|
191
|
+
] }),
|
|
192
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
193
|
+
/* @__PURE__ */ jsx("span", { style: { color: "oklch(0.72 0.18 155)", fontWeight: 700 }, children: stats.promoters }),
|
|
194
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
195
|
+
/* @__PURE__ */ jsx("span", { style: { color: "oklch(1 0 0/0.3)" }, children: "Promoters" })
|
|
196
|
+
] })
|
|
197
|
+
] }),
|
|
198
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: "0.75rem", paddingTop: "0.75rem", borderTop: "1px solid oklch(1 0 0/0.05)", display: "flex", justifyContent: "space-between", fontSize: "0.6875rem", color: "oklch(1 0 0/0.4)" }, children: [
|
|
199
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
200
|
+
"Avg: ",
|
|
201
|
+
stats.averageScore,
|
|
202
|
+
"/10"
|
|
203
|
+
] }),
|
|
204
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
205
|
+
stats.totalResponses,
|
|
206
|
+
" responses"
|
|
207
|
+
] })
|
|
208
|
+
] })
|
|
209
|
+
] });
|
|
210
|
+
}
|
|
211
|
+
export {
|
|
212
|
+
FeedbackCard,
|
|
213
|
+
FeedbackForm,
|
|
214
|
+
FeedbackProvider,
|
|
215
|
+
FeedbackTypeSelector,
|
|
216
|
+
FeedbackWidget,
|
|
217
|
+
NPSResults,
|
|
218
|
+
NPSSurvey,
|
|
219
|
+
PriorityBadge,
|
|
220
|
+
StatusBadge,
|
|
221
|
+
TypeBadge,
|
|
222
|
+
useFeedback,
|
|
223
|
+
useFeedbackAdmin,
|
|
224
|
+
useFeedbackConfig,
|
|
225
|
+
useFeedbackForm,
|
|
226
|
+
useNPS
|
|
227
|
+
};
|
|
228
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/hooks/index.ts","../src/components/index.tsx"],"sourcesContent":["export { FeedbackProvider, useFeedbackConfig } from '@geenius/feedback-react'\nexport { useFeedback, useFeedbackForm, useNPS, useFeedbackAdmin } from './hooks'\nexport type { FeedbackFilter } from './hooks'\nexport { StatusBadge, PriorityBadge, TypeBadge, FeedbackCard, FeedbackTypeSelector, FeedbackForm, FeedbackWidget, NPSSurvey, NPSResults } from './components'\nimport './styles.css'\nexport type { FeedbackItem, NPSResponse, FeedbackConfig, FeedbackStats, NPSStats, FeedbackType, FeedbackStatus, FeedbackPriority } from '@geenius/feedback-shared'\n","export { useFeedback, useFeedbackForm, useNPS, useFeedbackAdmin } from '@geenius/feedback-react'\nexport type { FeedbackFilter } from '@geenius/feedback-react'\n","import React, { useState } from 'react'\nimport type { FeedbackItem, FeedbackType, FeedbackStatus, FeedbackPriority, NPSResponse } from '@geenius/feedback-shared'\nimport { STATUS_CONFIG, PRIORITY_CONFIG, TYPE_CONFIG, FEEDBACK_TYPES, formatRelativeTime, calcNPSStats, getNPSCategory } from '@geenius/feedback-shared'\n\nexport function StatusBadge({ status }: { status: FeedbackStatus }) {\n return <span className={`feedback__status-badge feedback__status-badge--${status}`}>{STATUS_CONFIG[status].emoji} {STATUS_CONFIG[status].label}</span>\n}\n\nexport function PriorityBadge({ priority }: { priority: FeedbackPriority }) {\n return <span className={`feedback__priority-badge feedback__priority-badge--${priority}`}>{PRIORITY_CONFIG[priority].label}</span>\n}\n\nexport function TypeBadge({ type }: { type: FeedbackType }) {\n return <span className={`feedback__type-badge feedback__type-badge--${type}`}>{TYPE_CONFIG[type].icon} {TYPE_CONFIG[type].label}</span>\n}\n\nexport function FeedbackCard({ item, onVote, hasVoted, onClick }: { item: FeedbackItem; onVote?: (id: string) => void; hasVoted?: boolean; onClick?: (id: string) => void }) {\n return (\n <div className={`feedback__card feedback__card--${item.type}`} onClick={() => onClick?.(item.id)}>\n {onVote && (\n <button type=\"button\" className={`feedback__vote-btn ${hasVoted ? 'feedback__vote-btn--active' : 'feedback__vote-btn--inactive'}`} onClick={e => { e.stopPropagation(); onVote(item.id) }}>\n <span className=\"feedback__vote-btn-arrow\">{hasVoted ? '▲' : '△'}</span>\n <span>{item.votes}</span>\n </button>\n )}\n <div className=\"feedback__card-info\">\n <div className=\"feedback__card-badges\"><TypeBadge type={item.type} /><StatusBadge status={item.status} /><PriorityBadge priority={item.priority} /></div>\n <div className=\"feedback__card-title\">{item.title}</div>\n <div className=\"feedback__card-desc\">{item.description}</div>\n <div className=\"feedback__card-meta\">{item.userName && <span>{item.userName}</span>}<span>{formatRelativeTime(item.createdAt)}</span>{item.tags.map(t => <span key={t} className=\"feedback__tag\">{t}</span>)}</div>\n </div>\n </div>\n )\n}\n\nexport function FeedbackTypeSelector({ value, onChange }: { value: FeedbackType; onChange: (t: FeedbackType) => void }) {\n return (\n <div className=\"feedback__type-selector\">\n {FEEDBACK_TYPES.map(t => <button key={t} type=\"button\" onClick={() => onChange(t)}\n className={`feedback__type-tab ${value === t ? '' : 'feedback__type-tab--inactive'}`}\n style={value === t ? { background: TYPE_CONFIG[t].color, color: 'white' } : undefined}>{TYPE_CONFIG[t].icon} {TYPE_CONFIG[t].label}</button>)}\n </div>\n )\n}\n\nexport function FeedbackForm({ onSubmit, onClose }: { onSubmit: (data: { type: FeedbackType; title: string; description: string }) => Promise<string>; onClose?: () => void }) {\n const [type, setType] = useState<FeedbackType>('general')\n const [title, setTitle] = useState(''); const [desc, setDesc] = useState('')\n const [submitting, setSubmitting] = useState(false); const [error, setError] = useState<string | null>(null); const [success, setSuccess] = useState(false)\n const submit = async () => {\n if (!title.trim()) { setError('Title required'); return }; if (desc.length < 10) { setError('10+ chars'); return }\n setSubmitting(true); setError(null); try { await onSubmit({ type, title, description: desc }); setSuccess(true) } catch (e) { setError(String(e)) } finally { setSubmitting(false) }\n }\n if (success) return <div className=\"feedback__success\"><div className=\"feedback__success-icon\">🎉</div><div className=\"feedback__success-text\">Thank you!</div><div className=\"feedback__success-sub\">Feedback submitted</div></div>\n return (\n <div className=\"feedback__form\">\n <FeedbackTypeSelector value={type} onChange={setType} />\n <input type=\"text\" className=\"feedback__form-input\" placeholder=\"Title…\" value={title} onChange={e => setTitle(e.target.value)} />\n <textarea className=\"feedback__form-input feedback__form-textarea\" placeholder=\"Description…\" value={desc} onChange={e => setDesc(e.target.value)} />\n {error && <div className=\"feedback__form-error\">{error}</div>}\n <div className=\"feedback__form-actions\">\n {onClose && <button type=\"button\" className=\"feedback__btn feedback__btn--outline\" onClick={onClose}>Cancel</button>}\n <button type=\"button\" className=\"feedback__btn feedback__btn--primary\" onClick={submit} disabled={submitting}>{submitting ? 'Submitting…' : 'Submit'}</button>\n </div>\n </div>\n )\n}\n\nexport function FeedbackWidget({ onSubmit, position = 'right' }: { onSubmit: (data: { type: FeedbackType; title: string; description: string }) => Promise<string>; position?: 'left' | 'right' }) {\n const [isOpen, setIsOpen] = useState(false)\n return (<>\n <button type=\"button\" className=\"feedback__widget-trigger\" onClick={() => setIsOpen(true)}>Feedback</button>\n {isOpen && <div className=\"feedback__widget-overlay\" onClick={() => setIsOpen(false)}>\n <div className=\"feedback__widget-backdrop\" />\n <div className=\"feedback__widget-panel\" onClick={e => e.stopPropagation()}>\n <div className=\"feedback__widget-header\"><span className=\"feedback__widget-title\">Send Feedback</span><button type=\"button\" className=\"feedback__close-btn\" onClick={() => setIsOpen(false)}>✕</button></div>\n <FeedbackForm onSubmit={onSubmit} onClose={() => setIsOpen(false)} />\n </div>\n </div>}\n </>)\n}\n\nexport function NPSSurvey({ onSubmit, onDismiss }: { onSubmit: (score: number, comment?: string) => void; onDismiss: () => void }) {\n const [score, setScore] = useState<number | null>(null); const [comment, setComment] = useState(''); const [step, setStep] = useState<'score'|'comment'|'thanks'>('score')\n return (\n <div className=\"feedback__nps\">\n {step === 'score' && <div><div className=\"feedback__nps-header\"><span className=\"feedback__nps-title\">How likely to recommend us?</span><button type=\"button\" className=\"feedback__close-btn\" onClick={onDismiss}>✕</button></div><div className=\"feedback__nps-subtitle\">0 = Not at all · 10 = Extremely likely</div>\n <div className=\"feedback__nps-scores\">{Array.from({length:11}).map((_,i) => <button key={i} type=\"button\" className=\"feedback__nps-score-btn\" onClick={() => { setScore(i); setStep('comment') }}>{i}</button>)}</div><div className=\"feedback__nps-labels\"><span>Not likely</span><span>Very likely</span></div></div>}\n {step === 'comment' && <div><div className=\"feedback__nps-title\" style={{marginBottom: '0.75rem'}}>Score: {score}</div><textarea className=\"feedback__form-input feedback__form-textarea\" value={comment} onChange={e => setComment(e.target.value)} placeholder=\"Optional…\" /><button type=\"button\" className=\"feedback__btn feedback__btn--primary\" style={{width:'100%',marginTop:'0.75rem'}} onClick={() => { onSubmit(score!, comment||undefined); setStep('thanks') }}>Submit</button></div>}\n {step === 'thanks' && <div className=\"feedback__success\"><div className=\"feedback__success-icon\">🎉</div><div className=\"feedback__success-text\">Thank you!</div></div>}\n </div>\n )\n}\n\nexport function NPSResults({ responses }: { responses: NPSResponse[] }) {\n const stats = calcNPSStats(responses); const total = stats.totalResponses || 1\n const color = stats.npsScore >= 50 ? 'oklch(0.72 0.18 155)' : stats.npsScore >= 0 ? 'oklch(0.72 0.18 60)' : 'oklch(0.60 0.25 25)'\n return (\n <div className=\"feedback__nps-results\">\n <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:'0.5rem'}}><span>NPS Score</span><span className=\"feedback__nps-results-score\" style={{color}}>{stats.npsScore}</span></div>\n <div className=\"feedback__nps-bar\"><div className=\"feedback__nps-bar-detractors\" style={{width:`${(stats.detractors/total)*100}%`}} /><div className=\"feedback__nps-bar-passives\" style={{width:`${(stats.passives/total)*100}%`}} /><div className=\"feedback__nps-bar-promoters\" style={{width:`${(stats.promoters/total)*100}%`}} /></div>\n <div className=\"feedback__nps-breakdown\"><div><span style={{color:'oklch(0.60 0.25 25)',fontWeight:700}}>{stats.detractors}</span><br/><span style={{color:'oklch(1 0 0/0.3)'}}>Detractors</span></div><div><span style={{color:'oklch(0.72 0.18 60)',fontWeight:700}}>{stats.passives}</span><br/><span style={{color:'oklch(1 0 0/0.3)'}}>Passives</span></div><div><span style={{color:'oklch(0.72 0.18 155)',fontWeight:700}}>{stats.promoters}</span><br/><span style={{color:'oklch(1 0 0/0.3)'}}>Promoters</span></div></div>\n <div style={{marginTop:'0.75rem',paddingTop:'0.75rem',borderTop:'1px solid oklch(1 0 0/0.05)',display:'flex',justifyContent:'space-between',fontSize:'0.6875rem',color:'oklch(1 0 0/0.4)'}}><span>Avg: {stats.averageScore}/10</span><span>{stats.totalResponses} responses</span></div>\n </div>\n )\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
# ✦ @geenius-
|
|
1
|
+
# ✦ @geenius/feedback-shared\n\n> Geenius Feedback — Shared types & Convex schema\n\n---\n\n## Overview\nBuilt with Steve Jobs-level minimalism and Jony Ive-level craftsmanship, this package is designed to deliver unparalleled developer experience (DX) and rock-solid performance.\n\n## Installation\n\n```bash\npnpm add @geenius/feedback-shared\n```\n\n## Usage\n\n```typescript\nimport { init } from '@geenius/feedback-shared';\n\n// Initialize the module with absolute precision\ninit({\n mode: 'premium',\n});\n```\n\n## Architecture\n- **Zero-config**: It just works.\n- **Strictly Typed**: Fully written in TypeScript for flawless IntelliSense.\n- **Framework Agnostic**: seamlessly integrates into the Geenius ecosystem.\n\n---\n\n*Designed by Antigravity HQ*\n
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
type FeedbackType = 'bug' | 'feature' | 'general' | 'suggestion';
|
|
2
|
+
type FeedbackStatus = 'open' | 'under-review' | 'planned' | 'in-progress' | 'done' | 'declined';
|
|
3
|
+
type FeedbackPriority = 'low' | 'medium' | 'high' | 'critical';
|
|
4
|
+
type NPSCategory = 'detractor' | 'passive' | 'promoter';
|
|
5
|
+
interface Attachment {
|
|
6
|
+
url: string;
|
|
7
|
+
name: string;
|
|
8
|
+
size: number;
|
|
9
|
+
}
|
|
10
|
+
interface FeedbackItem {
|
|
11
|
+
id: string;
|
|
12
|
+
type: FeedbackType;
|
|
13
|
+
title: string;
|
|
14
|
+
description: string;
|
|
15
|
+
status: FeedbackStatus;
|
|
16
|
+
priority: FeedbackPriority;
|
|
17
|
+
userId?: string;
|
|
18
|
+
userEmail?: string;
|
|
19
|
+
userName?: string;
|
|
20
|
+
url?: string;
|
|
21
|
+
browser?: string;
|
|
22
|
+
os?: string;
|
|
23
|
+
tags: string[];
|
|
24
|
+
votes: number;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
updatedAt: string;
|
|
27
|
+
attachments?: Attachment[];
|
|
28
|
+
adminNote?: string;
|
|
29
|
+
}
|
|
30
|
+
interface NPSResponse {
|
|
31
|
+
id: string;
|
|
32
|
+
score: number;
|
|
33
|
+
comment?: string;
|
|
34
|
+
userId?: string;
|
|
35
|
+
submittedAt: string;
|
|
36
|
+
}
|
|
37
|
+
interface FeedbackConfig {
|
|
38
|
+
floatingWidget: boolean;
|
|
39
|
+
npsEnabled: boolean;
|
|
40
|
+
npsInterval: number;
|
|
41
|
+
categories: FeedbackType[];
|
|
42
|
+
allowAnonymous: boolean;
|
|
43
|
+
}
|
|
44
|
+
interface FeedbackStats {
|
|
45
|
+
total: number;
|
|
46
|
+
byType: Record<FeedbackType, number>;
|
|
47
|
+
byStatus: Record<FeedbackStatus, number>;
|
|
48
|
+
byPriority: Record<FeedbackPriority, number>;
|
|
49
|
+
}
|
|
50
|
+
interface NPSStats {
|
|
51
|
+
averageScore: number;
|
|
52
|
+
totalResponses: number;
|
|
53
|
+
promoters: number;
|
|
54
|
+
passives: number;
|
|
55
|
+
detractors: number;
|
|
56
|
+
npsScore: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @fileoverview Configuration factory for Geenius Feedback
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
interface ConfigureFeedbackOptions {
|
|
64
|
+
floatingWidget?: boolean;
|
|
65
|
+
npsEnabled?: boolean;
|
|
66
|
+
npsInterval?: number;
|
|
67
|
+
categories?: Array<'bug' | 'feature' | 'general' | 'suggestion'>;
|
|
68
|
+
allowAnonymous?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Configure the feedback system with custom options
|
|
72
|
+
* @param options Configuration options for the feedback system
|
|
73
|
+
* @returns FeedbackConfig object ready for use
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const config = configureFeedback({
|
|
77
|
+
* floatingWidget: true,
|
|
78
|
+
* npsEnabled: true,
|
|
79
|
+
* npsInterval: 7,
|
|
80
|
+
* categories: ['bug', 'feature', 'general'],
|
|
81
|
+
* allowAnonymous: true,
|
|
82
|
+
* })
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
declare function configureFeedback(options?: ConfigureFeedbackOptions): FeedbackConfig;
|
|
86
|
+
/**
|
|
87
|
+
* Default feedback configuration
|
|
88
|
+
*/
|
|
89
|
+
declare const defaultFeedbackConfig: FeedbackConfig;
|
|
90
|
+
|
|
91
|
+
declare const STATUS_CONFIG: Record<FeedbackStatus, {
|
|
92
|
+
label: string;
|
|
93
|
+
color: string;
|
|
94
|
+
emoji: string;
|
|
95
|
+
}>;
|
|
96
|
+
declare const PRIORITY_CONFIG: Record<FeedbackPriority, {
|
|
97
|
+
label: string;
|
|
98
|
+
color: string;
|
|
99
|
+
}>;
|
|
100
|
+
declare const TYPE_CONFIG: Record<FeedbackType, {
|
|
101
|
+
label: string;
|
|
102
|
+
icon: string;
|
|
103
|
+
color: string;
|
|
104
|
+
}>;
|
|
105
|
+
declare const FEEDBACK_TYPES: FeedbackType[];
|
|
106
|
+
declare const FEEDBACK_STATUSES: FeedbackStatus[];
|
|
107
|
+
declare const FEEDBACK_PRIORITIES: FeedbackPriority[];
|
|
108
|
+
declare function getStatusTransitions(status: FeedbackStatus): FeedbackStatus[];
|
|
109
|
+
declare function getNPSCategory(score: number): 'detractor' | 'passive' | 'promoter';
|
|
110
|
+
declare function calcNPSScore(responses: NPSResponse[]): number;
|
|
111
|
+
declare function calcNPSStats(responses: NPSResponse[]): NPSStats;
|
|
112
|
+
declare function calcFeedbackStats(items: FeedbackItem[]): FeedbackStats;
|
|
113
|
+
declare function formatRelativeTime(dateStr: string): string;
|
|
114
|
+
|
|
115
|
+
export { type Attachment, type ConfigureFeedbackOptions, FEEDBACK_PRIORITIES, FEEDBACK_STATUSES, FEEDBACK_TYPES, type FeedbackConfig, type FeedbackItem, type FeedbackPriority, type FeedbackStats, type FeedbackStatus, type FeedbackType, type NPSCategory, type NPSResponse, type NPSStats, PRIORITY_CONFIG, STATUS_CONFIG, TYPE_CONFIG, calcFeedbackStats, calcNPSScore, calcNPSStats, configureFeedback, defaultFeedbackConfig, formatRelativeTime, getNPSCategory, getStatusTransitions };
|