@akinon/pz-theme 2.0.95-beta.1 → 2.0.95-rc.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +33 -15
  2. package/package.json +4 -4
  3. package/src/__tests__/auth-commerce-events.test.tsx +1 -5
  4. package/src/__tests__/auth-form-error-block.test.tsx +0 -2
  5. package/src/__tests__/auth-form-validation.test.tsx +0 -2
  6. package/src/__tests__/auth-slot-coverage.test.ts +1 -9
  7. package/src/__tests__/auth-step-title.test.tsx +0 -2
  8. package/src/__tests__/detached-submit-state.test.tsx +2 -80
  9. package/src/__tests__/forgot-password-composed.test.tsx +0 -2
  10. package/src/__tests__/otp-form-composed.test.tsx +0 -2
  11. package/src/__tests__/password-reset-step.test.tsx +0 -2
  12. package/src/__tests__/register-form-composed.test.tsx +4 -253
  13. package/src/__tests__/registry-parity.test.ts +0 -12
  14. package/src/auth/auth-field-errors.tsx +0 -31
  15. package/src/blocks/account-button-block.tsx +0 -25
  16. package/src/blocks/add-to-cart-block.tsx +0 -15
  17. package/src/blocks/auth-field-block.tsx +3 -13
  18. package/src/blocks/auth-flow-block.tsx +3 -45
  19. package/src/blocks/auth-form-block.tsx +54 -337
  20. package/src/blocks/block-renderer-registry.tsx +0 -8
  21. package/src/blocks/button-block.tsx +13 -43
  22. package/src/blocks/change-password-form-block.tsx +0 -15
  23. package/src/blocks/forgot-password-block.tsx +9 -132
  24. package/src/blocks/newsletter-form-block.tsx +0 -16
  25. package/src/blocks/otp-form-block.tsx +67 -161
  26. package/src/blocks/profile-form-block.tsx +0 -13
  27. package/src/blocks/register-form-block.tsx +110 -362
  28. package/src/chrome/__tests__/theme-config-source.test.ts +1 -2
  29. package/src/chrome/placeholder-slugs.ts +0 -3
  30. package/src/chrome/route-slug.ts +0 -11
  31. package/src/index.ts +0 -10
  32. package/src/overlays/__tests__/modal-registry.test.ts +1 -5
  33. package/src/overlays/modal-chrome-css.ts +1 -8
  34. package/src/overlays/modal-preview-host.tsx +2 -7
  35. package/src/overlays/modal-registry.ts +1 -38
  36. package/src/overlays/overlay-surface.tsx +0 -23
  37. package/src/overlays/overlay-tokens.ts +0 -12
  38. package/src/overlays/theme-modal-mount.tsx +6 -85
  39. package/src/utils/visibility-rules.ts +0 -114
  40. package/src/__tests__/auth-captcha.test.tsx +0 -261
  41. package/src/__tests__/auth-destination.test.tsx +0 -348
  42. package/src/__tests__/auth-error-reading.test.ts +0 -232
  43. package/src/__tests__/auth-flow-scope.test.tsx +0 -162
  44. package/src/__tests__/auth-form-success-block.test.tsx +0 -429
  45. package/src/__tests__/block-action-audience.test.ts +0 -154
  46. package/src/__tests__/form-state-composition.test.tsx +0 -484
  47. package/src/__tests__/modal-login-close.test.tsx +0 -366
  48. package/src/__tests__/reset-password-composed.test.tsx +0 -385
  49. package/src/auth/auth-captcha.tsx +0 -125
  50. package/src/auth/auth-destination.ts +0 -168
  51. package/src/auth/form-state-context.tsx +0 -170
  52. package/src/auth/form-success-context.tsx +0 -56
  53. package/src/auth/read-auth-error.ts +0 -332
  54. package/src/blocks/auth-success-block.tsx +0 -85
  55. package/src/blocks/captcha-block.tsx +0 -61
  56. package/src/blocks/form-state-block.tsx +0 -84
  57. package/src/blocks/reset-password-block.tsx +0 -717
  58. package/src/overlays/__tests__/modal-loading.test.tsx +0 -235
  59. package/src/overlays/modal-host-context.tsx +0 -66
  60. package/src/overlays/overlay-loading.tsx +0 -144
@@ -3,9 +3,7 @@
3
3
  import React from 'react';
4
4
  import NextLink from 'next/link';
5
5
  import { useSession } from 'next-auth/react';
6
- import { usePathname } from 'next/navigation';
7
6
  import { getResponsiveValue, partAttrs } from '../utils';
8
- import { withReturnPath } from '../auth/auth-destination';
9
7
  import useBlockAction from '../hooks/use-block-action';
10
8
  import { BlockRendererProps } from './block-renderer-registry';
11
9
  import { readToggle } from './product-block-utils';
@@ -52,31 +50,8 @@ const AccountButtonBlock = ({
52
50
  getResponsiveValue(block.properties?.[key], currentBreakpoint, fallback)
53
51
  );
54
52
 
55
- /**
56
- * Whether a guest click records where the shopper was standing.
57
- *
58
- * On by default, and it has to be here rather than in the form: this control
59
- * is the only thing that knows the answer. pz's own route guard redirects to
60
- * the auth page with no parameter at all, so a login PAGE had nothing to
61
- * return to — which is why the form's "go back where they came from" mode
62
- * was unbuildable. Appends `?callbackUrl=<current path>`, which is the key
63
- * next-auth and the brands' own views already read; the form ignores
64
- * anything that is not a path on this origin.
65
- *
66
- * Nothing changes for a drawer: it never navigates, so there is no href to
67
- * record on. A brand that tracks its login links by url turns it off.
68
- */
69
- const rememberReturn = readToggle(
70
- block.properties?.rememberReturn,
71
- currentBreakpoint,
72
- true
73
- );
74
- const pathname = usePathname();
75
-
76
53
  const href = isAuthenticated
77
54
  ? prop('accountHref', '/account')
78
- : rememberReturn
79
- ? withReturnPath(prop('loginHref', '/auth'), pathname)
80
55
  : prop('loginHref', '/auth');
81
56
  const label = isAuthenticated
82
57
  ? prop('accountLabel', 'Account')
@@ -10,7 +10,6 @@ import {
10
10
  emitCommerceEvent,
11
11
  readItemsCurrency
12
12
  } from '../utils/analytics';
13
- import { useHostModalCloser } from '../overlays/modal-host-context';
14
13
  import { BlockRendererProps } from './block-renderer-registry';
15
14
  import {
16
15
  DesignerPlaceholder,
@@ -119,19 +118,6 @@ const AddToCartBlock = ({
119
118
  getResponsiveValue(block.properties?.[key], currentBreakpoint, fallback)
120
119
  );
121
120
 
122
- /**
123
- * Whether finishing closes the modal this block is inside. OFF by default
124
- * here, because this block's success state is something the shopper is meant
125
- * to read — see `useHostModalCloser`.
126
- */
127
- const closeHostModalOnSuccess = readToggle(
128
- block.properties?.closeHostModalOnSuccess,
129
- currentBreakpoint,
130
- false
131
- );
132
- const closeHostModal = useHostModalCloser(closeHostModalOnSuccess);
133
-
134
-
135
121
  const label = prop('label', 'Add to Cart');
136
122
  const addingLabel = prop('addingLabel', 'Adding…');
137
123
  const addedLabel = prop('addedLabel', 'Added');
@@ -300,7 +286,6 @@ const AddToCartBlock = ({
300
286
  // by the mini-basket chrome block) has to be refreshed explicitly.
301
287
  dispatch(basketApi.util.invalidateTags(['Basket', 'MiniBasket']));
302
288
  setFeedback('added');
303
- closeHostModal();
304
289
  emitCommerceEvent('add_to_cart', {
305
290
  currency: readItemsCurrency(product),
306
291
  items: [buildCommerceItem(product, { quantity })]
@@ -20,7 +20,7 @@ import { BlockRendererProps } from './block-renderer-registry';
20
20
  * form owns those. Standalone (outside any form) it still renders, but
21
21
  * nothing collects its value, which the designer sees immediately.
22
22
  *
23
- * Properties: fieldType, label, placeholder, showLabel, required, autoComplete, and for
23
+ * Properties: fieldType, label, placeholder, showLabel, required, and for
24
24
  * a `gender` field the two option captions (femaleLabel, maleLabel).
25
25
  * Parts: field, label, input, error.
26
26
  */
@@ -143,16 +143,6 @@ const AuthFieldBlock = ({
143
143
  : preset.type;
144
144
 
145
145
  const label = prop('label', preset.label);
146
- /**
147
- * What a password manager is told this box is for.
148
- *
149
- * The preset was compiled in, which made one screen wrong on purpose: the
150
- * `password` preset says `current-password`, so a composed SIGN-UP or a
151
- * reset screen told the manager to offer a saved password instead of
152
- * generating a new one, and what the shopper then typed was never saved.
153
- * Absent keeps the preset, so every published field is untouched.
154
- */
155
- const autoComplete = prop('autoComplete', '').trim() || preset.autoComplete;
156
146
  const placeholder = prop('placeholder', '');
157
147
  const showLabel = readToggle(
158
148
  block.properties?.showLabel,
@@ -226,7 +216,7 @@ const AuthFieldBlock = ({
226
216
  */
227
217
  <select
228
218
  name={controlName}
229
- autoComplete={autoComplete}
219
+ autoComplete={preset.autoComplete}
230
220
  defaultValue=""
231
221
  aria-label={showLabel ? undefined : label}
232
222
  aria-invalid={errorMessage ? true : undefined}
@@ -245,7 +235,7 @@ const AuthFieldBlock = ({
245
235
  <input
246
236
  type={controlType}
247
237
  name={controlName}
248
- autoComplete={autoComplete}
238
+ autoComplete={preset.autoComplete}
249
239
  placeholder={placeholder || undefined}
250
240
  aria-label={showLabel ? undefined : label}
251
241
  aria-invalid={errorMessage ? true : undefined}
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
3
  import React, { useEffect } from 'react';
4
- import { useSession } from 'next-auth/react';
5
4
  import { getResponsiveValue, partAttrs } from '../utils';
6
5
  import {
7
6
  ActiveAuthStepContext,
8
7
  AuthFlowIdContext,
8
+ DEFAULT_AUTH_FLOW_ID,
9
9
  goBackAuthStep,
10
10
  registerAuthFlowMount,
11
11
  useAuthFlowState
@@ -74,33 +74,9 @@ const AuthFlowBlock = ({
74
74
  getResponsiveValue(block.properties?.[key], currentBreakpoint, fallback)
75
75
  );
76
76
 
77
- /**
78
- * The name this journey answers to on the bus.
79
- *
80
- * Authored, it is shared: two flows carrying the same name show the same step
81
- * — deliberate for one journey rendered twice, and for a trigger outside the
82
- * flow that names `<flowId>:<step>`.
83
- *
84
- * Empty, it is the BLOCK's own, because the alternative was a collision the
85
- * moment a brand did what the composition invites: a journey in the header
86
- * drawer and a second one in a tab or a page body both fell back to one
87
- * shared name, so opening the drawer on "register" moved the page's journey
88
- * with it, and closing the drawer reset it. `DEFAULT_AUTH_FLOW_ID` stays the
89
- * fallback for controls that know no flow at all — see `resolveAuthStepTarget`
90
- * — so a composition that wants to be reachable that way names itself.
91
- */
92
- const flowId = prop('flowId', '').trim() || `flow-${block.id}`;
77
+ const flowId = prop('flowId', '').trim() || DEFAULT_AUTH_FLOW_ID;
93
78
  const initialStep = prop('initialStep', '').trim();
94
79
  const previewStep = prop('previewStep', '').trim();
95
- /**
96
- * The step a shopper who is ALREADY signed in lands on.
97
- *
98
- * The state picks the step, which is the flow's whole idea — so a member who
99
- * opens the drawer gets "Hoş geldin / Hesabım / Çıkış" composed out of
100
- * ordinary blocks instead of the login form they have no use for. Empty
101
- * keeps the historical behaviour: the flow does not care about the session.
102
- */
103
- const signedInStep = prop('signedInStep', '').trim();
104
80
  const backLabel = prop('backLabel', 'Back');
105
81
  const showBack = readToggle(
106
82
  block.properties?.showBack,
@@ -116,13 +92,6 @@ const AuthFlowBlock = ({
116
92
  );
117
93
 
118
94
  const flowState = useAuthFlowState(isDesigner ? '' : flowId);
119
- const { status } = useSession();
120
- /**
121
- * `loading` is not treated as signed in: the flow would open on the member
122
- * step for a guest and then swap. The other way round — a member seeing the
123
- * login step for a beat — is the state they are being moved out of anyway.
124
- */
125
- const isSignedIn = status === 'authenticated' && !isDesigner;
126
95
 
127
96
  useEffect(() => {
128
97
  if (isDesigner) return undefined;
@@ -155,20 +124,9 @@ const AuthFlowBlock = ({
155
124
  if (selected) return stepKeyOf(selected, currentBreakpoint);
156
125
  }
157
126
 
158
- /**
159
- * A step the shopper NAVIGATED to still wins over the member step: a
160
- * signed-in shopper who taps "change password" inside the journey is
161
- * asking for that step, and answering with the welcome card would be the
162
- * flow overruling them. The member step is the ENTRY, so it only leads
163
- * while the bus has nothing to say.
164
- */
165
127
  const candidates = isDesigner
166
128
  ? [previewStep, initialStep]
167
- : [
168
- flowState?.active ?? '',
169
- ...(isSignedIn ? [signedInStep] : []),
170
- initialStep
171
- ];
129
+ : [flowState?.active ?? '', initialStep];
172
130
 
173
131
  for (const candidate of candidates) {
174
132
  if (candidate && stepKeys.includes(candidate)) return candidate;