@meith/plugin-dues 0.35.1 → 0.36.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meith/plugin-dues",
3
- "version": "0.35.1",
3
+ "version": "0.36.0",
4
4
  "description": "Membership dues for a Meith board: Stripe-backed subscriptions as a contained plugin.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,8 +20,9 @@
20
20
  "access": "public"
21
21
  },
22
22
  "dependencies": {
23
- "@meith/plugin-kit": "^0.35.1",
24
- "@meith/theme-kit": "^0.35.1"
23
+ "@meith/plugin-kit": "^0.36.0",
24
+ "@meith/theme-kit": "^0.36.0",
25
+ "@meith/ui": "^0.36.0"
25
26
  },
26
27
  "peerDependencies": {
27
28
  "react": "^19.2.0"
@@ -57,7 +57,7 @@ export function createDues(input: DuesConfigInput = {}): PluginDefinition {
57
57
  return definePlugin({
58
58
  key: 'dues',
59
59
  name: 'Dues',
60
- version: '0.35.1',
60
+ version: '0.36.0',
61
61
  description: en['dues.definition.description'].replace(
62
62
  '{label}',
63
63
  staticConfig.label.toLowerCase(),
package/src/ui/admin.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from 'react'
2
2
 
3
3
  import { PLUGIN_CARD, PLUGIN_NOTE, type PluginAdminPageContext } from '@meith/plugin-kit'
4
+ import { buttonVariants, controlVariants } from '@meith/ui'
4
5
 
5
6
  import { type DuesConfig, MAX_GRACE_DAYS } from '../config'
6
7
  import { formatMinor } from '../money'
@@ -24,14 +25,9 @@ const QUIET_PANEL = PLUGIN_NOTE
24
25
  const CARD = PLUGIN_CARD
25
26
  const TH = 'px-2 py-1.5 text-left text-xs font-medium text-muted-foreground'
26
27
  const TD = 'px-2 py-1.5 align-top'
27
- const INPUT =
28
- 'rounded-md border border-border bg-background px-3 py-2 text-sm ' +
29
- 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
30
- const ACT_BUTTON =
31
- 'inline-flex h-8 items-center justify-center rounded-md border border-transparent ' +
32
- 'bg-primary px-3 text-sm font-medium text-primary-foreground hover:bg-primary-hover'
33
- const QUIET_BUTTON =
34
- 'inline-flex h-8 items-center justify-center rounded-md border border-border px-3 text-sm'
28
+ const INPUT = controlVariants()
29
+ const ACT_BUTTON = buttonVariants({ variant: 'primary', size: 'sm' })
30
+ const QUIET_BUTTON = buttonVariants({ variant: 'outline', size: 'sm' })
35
31
 
36
32
  function fmt(date: Date, context: PluginAdminPageContext): string {
37
33
  return context.t.parts(date, { dateStyle: 'medium', timeStyle: 'short', timeZone: 'UTC' })
@@ -127,7 +123,7 @@ export async function StatusPage({
127
123
  <h2 className="font-heading text-lg font-semibold">
128
124
  {context.t.t('dues.admin.status.working')}
129
125
  </h2>
130
- <dl className="flex flex-col gap-1 text-sm">
126
+ <dl className="flex min-w-0 flex-col gap-2 text-sm">
131
127
  <div className="flex justify-between gap-2">
132
128
  <dt className="text-muted-foreground">{context.t.t('dues.admin.status.secret')}</dt>
133
129
  <dd>
@@ -584,19 +580,19 @@ export async function CodesPage({
584
580
  action="/admin/api/plugins/dues/codes/create"
585
581
  className="grid gap-3 sm:grid-cols-2"
586
582
  >
587
- <label className="flex flex-col gap-1 text-sm">
583
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
588
584
  <span className="text-xs text-muted-foreground">
589
585
  {context.t.t('dues.admin.codes.codeHelp')}
590
586
  </span>
591
587
  <input name="code" autoComplete="off" placeholder="LAUNCH50" className={INPUT} />
592
588
  </label>
593
- <label className="flex flex-col gap-1 text-sm">
589
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
594
590
  <span className="text-xs text-muted-foreground">
595
591
  {context.t.t('dues.admin.codes.percentHelp')}
596
592
  </span>
597
593
  <input type="number" name="percent" min={1} max={100} required className={INPUT} />
598
594
  </label>
599
- <label className="flex flex-col gap-1 text-sm">
595
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
600
596
  <span className="text-xs text-muted-foreground">
601
597
  {context.t.t('dues.admin.codes.planHelp')}
602
598
  </span>
@@ -609,13 +605,13 @@ export async function CodesPage({
609
605
  ))}
610
606
  </select>
611
607
  </label>
612
- <label className="flex flex-col gap-1 text-sm">
608
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
613
609
  <span className="text-xs text-muted-foreground">
614
610
  {context.t.t('dues.admin.codes.redemptionCap')}
615
611
  </span>
616
612
  <input type="number" name="max" min={1} className={INPUT} />
617
613
  </label>
618
- <label className="flex flex-col gap-1 text-sm">
614
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
619
615
  <span className="text-xs text-muted-foreground">
620
616
  {context.t.t('dues.admin.codes.expiresHelp')}
621
617
  </span>
@@ -731,26 +727,26 @@ function PlanFields({ plan, context }: { plan?: PlanRow; context: PluginAdminPag
731
727
  const period = plan === undefined ? { length: 90, unit: 'days' } : planPeriodParts(plan)
732
728
  return (
733
729
  <>
734
- <label className="flex flex-col gap-1 text-sm">
730
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
735
731
  <span className="text-xs text-muted-foreground">
736
732
  {context.t.t('dues.admin.plans.name')}
737
733
  </span>
738
734
  <input name="name" defaultValue={plan?.name ?? ''} required className={INPUT} />
739
735
  </label>
740
- <label className="flex flex-col gap-1 text-sm">
736
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
741
737
  <span className="text-xs text-muted-foreground">
742
738
  {context.t.t('dues.admin.plans.description')}
743
739
  </span>
744
740
  <input name="description" defaultValue={plan?.description ?? ''} className={INPUT} />
745
741
  </label>
746
- <label className="flex flex-col gap-1 text-sm">
742
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
747
743
  <span className="text-xs text-muted-foreground">
748
744
  {context.t.t('dues.admin.plans.giftGroup')}
749
745
  </span>
750
746
  <input name="group" defaultValue={plan?.groupKey ?? ''} required className={INPUT} />
751
747
  </label>
752
- <div className="grid grid-cols-2 gap-3">
753
- <label className="flex flex-col gap-1 text-sm">
748
+ <div className="grid gap-4 sm:grid-cols-2">
749
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
754
750
  <span className="text-xs text-muted-foreground">
755
751
  {context.t.t('dues.admin.plans.price')}
756
752
  </span>
@@ -763,7 +759,7 @@ function PlanFields({ plan, context }: { plan?: PlanRow; context: PluginAdminPag
763
759
  className={INPUT}
764
760
  />
765
761
  </label>
766
- <label className="flex flex-col gap-1 text-sm">
762
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
767
763
  <span className="text-xs text-muted-foreground">
768
764
  {context.t.t('dues.admin.plans.currency')}
769
765
  </span>
@@ -778,8 +774,8 @@ function PlanFields({ plan, context }: { plan?: PlanRow; context: PluginAdminPag
778
774
  </label>
779
775
  </div>
780
776
  {(plan === undefined || plan.mode === 'fixed') && (
781
- <div className="grid grid-cols-2 gap-3">
782
- <label className="flex flex-col gap-1 text-sm">
777
+ <div className="grid gap-4 sm:grid-cols-2">
778
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
783
779
  <span className="text-xs text-muted-foreground">
784
780
  {context.t.t('dues.admin.plans.length')}
785
781
  </span>
@@ -791,7 +787,7 @@ function PlanFields({ plan, context }: { plan?: PlanRow; context: PluginAdminPag
791
787
  className={INPUT}
792
788
  />
793
789
  </label>
794
- <label className="flex flex-col gap-1 text-sm">
790
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
795
791
  <span className="text-xs text-muted-foreground">
796
792
  {context.t.t('dues.admin.plans.unit')}
797
793
  </span>
@@ -805,7 +801,7 @@ function PlanFields({ plan, context }: { plan?: PlanRow; context: PluginAdminPag
805
801
  </div>
806
802
  )}
807
803
  {(plan === undefined || plan.mode === 'auto') && (
808
- <label className="flex flex-col gap-1 text-sm">
804
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
809
805
  <span className="text-xs text-muted-foreground">
810
806
  {context.t.t('dues.admin.plans.interval')}
811
807
  </span>
@@ -816,7 +812,7 @@ function PlanFields({ plan, context }: { plan?: PlanRow; context: PluginAdminPag
816
812
  </label>
817
813
  )}
818
814
  {(plan === undefined || plan.mode === 'auto') && (
819
- <label className="flex flex-col gap-1 text-sm">
815
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
820
816
  <span className="text-xs text-muted-foreground">
821
817
  {context.t.t('dues.admin.plans.stripePrice')}
822
818
  </span>
@@ -937,14 +933,14 @@ export async function PlansAdminPage({
937
933
  action="/admin/api/plugins/dues/plans/create"
938
934
  className="flex flex-col gap-3"
939
935
  >
940
- <div className="grid grid-cols-2 gap-3">
941
- <label className="flex flex-col gap-1 text-sm">
936
+ <div className="grid gap-4 sm:grid-cols-2">
937
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
942
938
  <span className="text-xs text-muted-foreground">
943
939
  {context.t.t('dues.admin.plans.key')}
944
940
  </span>
945
941
  <input name="key" placeholder="day-pass" required className={INPUT} />
946
942
  </label>
947
- <label className="flex flex-col gap-1 text-sm">
943
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
948
944
  <span className="text-xs text-muted-foreground">
949
945
  {context.t.t('dues.admin.plans.bills')}
950
946
  </span>
package/src/ui/pages.tsx CHANGED
@@ -2,6 +2,7 @@ import type { ReactNode } from 'react'
2
2
 
3
3
  import { PLUGIN_CARD, PLUGIN_NOTE, type PluginPageContext } from '@meith/plugin-kit'
4
4
  import type { Translator } from '@meith/theme-kit'
5
+ import { buttonVariants, controlVariants } from '@meith/ui'
5
6
 
6
7
  import type { DuesConfig } from '../config'
7
8
  import { formatMinor } from '../money'
@@ -18,14 +19,9 @@ import {
18
19
  const QUIET_PANEL = PLUGIN_NOTE
19
20
 
20
21
  const CARD = PLUGIN_CARD
21
- const INPUT =
22
- 'w-full rounded-md border border-border bg-background px-3 py-2 text-sm ' +
23
- 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring'
24
- const BUY_BUTTON =
25
- 'inline-flex h-9 items-center justify-center rounded-md border border-transparent ' +
26
- 'bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary-hover'
27
- const QUIET_BUTTON =
28
- 'inline-flex h-9 items-center justify-center rounded-md border border-border px-3 text-sm'
22
+ const INPUT = controlVariants()
23
+ const BUY_BUTTON = buttonVariants({ variant: 'primary' })
24
+ const QUIET_BUTTON = buttonVariants({ variant: 'outline', size: 'sm' })
29
25
 
30
26
  function fmtDate(date: Date, t: Translator): ReactNode {
31
27
  const label = t.parts(date, {
@@ -180,10 +176,14 @@ function PlanCard({
180
176
  </div>
181
177
 
182
178
  {viewerSignedIn ? (
183
- <form method="post" action="/api/plugins/dues/checkout" className="flex flex-col gap-3">
179
+ <form
180
+ method="post"
181
+ action="/api/plugins/dues/checkout"
182
+ className="mt-auto flex flex-col gap-3"
183
+ >
184
184
  <input type="hidden" name="plan" value={plan.key} />
185
185
  {plan.giftable && (
186
- <label className="flex flex-col gap-1 text-sm">
186
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
187
187
  <span className="text-xs text-muted-foreground">{t.t('dues.plan.gift')}</span>
188
188
  <input
189
189
  name="recipient"
@@ -193,7 +193,7 @@ function PlanCard({
193
193
  />
194
194
  </label>
195
195
  )}
196
- <label className="flex flex-col gap-1 text-sm">
196
+ <label className="flex min-w-0 flex-col gap-2 text-sm">
197
197
  <span className="text-xs text-muted-foreground">{t.t('dues.plan.discountCode')}</span>
198
198
  <input name="code" defaultValue={defaultCode} autoComplete="off" className={INPUT} />
199
199
  </label>