@motor-hero/ui-kit 0.37.1 → 0.37.3

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": "@motor-hero/ui-kit",
3
- "version": "0.37.1",
3
+ "version": "0.37.3",
4
4
  "description": "Componentes React reutilizáveis para o ecossistema MotorHero — shadcn/ui + Tailwind CSS v4",
5
5
  "author": "MotorHero",
6
6
  "license": "UNLICENSED",
@@ -64,13 +64,21 @@ export interface FormDialogProps extends Omit<BaseDialogProps, "contentWrapper">
64
64
  * plain BaseDialog.
65
65
  */
66
66
  export function FormDialog({ onSubmit, ...rest }: FormDialogProps) {
67
+ // O conteúdo do dialog é portalado para o body, mas eventos React sobem pela
68
+ // árvore React, não pela do DOM: sem stopPropagation, o submit deste form
69
+ // chega ao <form> da página que renderiza o dialog e dispara o submit dela.
70
+ // Precisa ser síncrono — handlers de RHF são assíncronos (resolver).
71
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
72
+ e.stopPropagation()
73
+ onSubmit?.(e)
74
+ }
67
75
  return (
68
76
  <BaseDialog
69
77
  {...rest}
70
78
  contentWrapper={
71
79
  onSubmit
72
80
  ? (content) => (
73
- <form onSubmit={onSubmit} className="flex min-h-0 flex-1 flex-col">
81
+ <form onSubmit={handleSubmit} className="flex min-h-0 flex-1 flex-col">
74
82
  {content}
75
83
  </form>
76
84
  )
@@ -3,17 +3,43 @@ import { useState } from "react"
3
3
  export type UseCompanySubdomainOptions = {
4
4
  enableOverride?: boolean
5
5
  overrideStorageKey?: string
6
+ /**
7
+ * Host labels that are *not* tenants. A product whose default host carries
8
+ * a label of its own (`app.example.com`, `admin.example.com`) must list it
9
+ * here, or that label is read as a tenant slug and sent downstream as one.
10
+ *
11
+ * Added to the built-in `www`; `localhost` is always excluded structurally.
12
+ * Case-insensitive.
13
+ */
14
+ reservedSubdomains?: string[]
6
15
  }
7
16
 
8
17
  export type UseCompanySubdomainResult = {
9
18
  subdomain: string | undefined
10
19
  }
11
20
 
12
- export function getSubdomain(hostname: string): string | undefined {
21
+ const ALWAYS_RESERVED = ["www", "localhost"]
22
+
23
+ /**
24
+ * The tenant slug in a hostname, or `undefined` when there is none.
25
+ *
26
+ * The first label is only a tenant if it isn't reserved. Callers whose
27
+ * default host is `app.<domain>` must pass `["app"]` (plus any sibling
28
+ * surfaces like `admin`), otherwise visiting the default host yields the
29
+ * literal `"app"` as if it were a customer.
30
+ */
31
+ export function getSubdomain(
32
+ hostname: string,
33
+ reservedSubdomains: string[] = [],
34
+ ): string | undefined {
13
35
  const labels = hostname.split(".")
14
36
  if (labels.length < 2) return undefined
15
37
  const first = labels[0]
16
- if (!first || first === "www" || first === "localhost") return undefined
38
+ if (!first) return undefined
39
+ const reserved = [...ALWAYS_RESERVED, ...reservedSubdomains].map((label) =>
40
+ label.toLowerCase(),
41
+ )
42
+ if (reserved.includes(first.toLowerCase())) return undefined
17
43
  return first
18
44
  }
19
45
 
@@ -35,8 +61,11 @@ function resolveOverride(storageKey: string): string | undefined {
35
61
  export function useCompanySubdomain(
36
62
  opts: UseCompanySubdomainOptions = {},
37
63
  ): UseCompanySubdomainResult {
38
- const { enableOverride = false, overrideStorageKey = "company-subdomain" } =
39
- opts
64
+ const {
65
+ enableOverride = false,
66
+ overrideStorageKey = "company-subdomain",
67
+ reservedSubdomains = [],
68
+ } = opts
40
69
 
41
70
  const [subdomain] = useState<string | undefined>(() => {
42
71
  if (enableOverride) {
@@ -44,7 +73,7 @@ export function useCompanySubdomain(
44
73
  if (override) return override
45
74
  }
46
75
  if (typeof window === "undefined") return undefined
47
- return getSubdomain(window.location.hostname)
76
+ return getSubdomain(window.location.hostname, reservedSubdomains)
48
77
  })
49
78
 
50
79
  return { subdomain }