@ews-admin/global-design-system 1.19.0 → 1.22.1

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/dist/index.js CHANGED
@@ -224,9 +224,36 @@ function formatCurrency(amount, currency = CURRENCY) {
224
224
  currency,
225
225
  }).format(amount);
226
226
  }
227
+ /**
228
+ * Parses a date value the way every date coming from these platforms'
229
+ * Java/Kotlin backends actually shows up, without the classic off-by-one
230
+ * timezone bug.
231
+ *
232
+ * A bare "YYYY-MM-DD" string is parsed by `new Date(...)` as UTC midnight
233
+ * (per the ECMAScript spec), which then shifts a day earlier once formatted
234
+ * in any timezone behind UTC. This function parses date-only strings (and
235
+ * Jackson's `[year, month, day, ...]` LocalDate/LocalDateTime array
236
+ * serialization) as local calendar components instead. Full ISO datetime
237
+ * strings (with a time and/or timezone), Date objects, and numeric
238
+ * timestamps are unaffected and still go through the normal `new Date(...)`
239
+ * parse.
240
+ */
241
+ function parseDateSafe(date) {
242
+ if (Array.isArray(date)) {
243
+ const [y, m, d, h = 0, min = 0, s = 0] = date;
244
+ return new Date(y, m - 1, d, h, min, s);
245
+ }
246
+ if (typeof date === "string") {
247
+ const dateOnlyMatch = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date);
248
+ if (dateOnlyMatch) {
249
+ return new Date(Number(dateOnlyMatch[1]), Number(dateOnlyMatch[2]) - 1, Number(dateOnlyMatch[3]));
250
+ }
251
+ }
252
+ return new Date(date);
253
+ }
227
254
  function formatDate(date, options) {
228
255
  const { locale = "en-US", ...intlOptions } = options ?? {};
229
- const dateObj = new Date(date);
256
+ const dateObj = parseDateSafe(date);
230
257
  return new Intl.DateTimeFormat(locale, {
231
258
  year: "numeric",
232
259
  month: "long",
@@ -34209,6 +34236,7 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34209
34236
  this.resizeObserver = null;
34210
34237
  this.previousCropSize = null;
34211
34238
  this.isInitialized = false;
34239
+ this.dragInteractionSource = null;
34212
34240
  this.state = {
34213
34241
  cropSize: null,
34214
34242
  hasWheelJustStarted: false,
@@ -34332,7 +34360,7 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34332
34360
  this.currentDoc.addEventListener("mousemove", this.onMouseMove);
34333
34361
  this.currentDoc.addEventListener("mouseup", this.onDragStopped);
34334
34362
  this.saveContainerPosition();
34335
- this.onDragStart(Cropper.getMousePoint(e));
34363
+ this.onDragStart(Cropper.getMousePoint(e), "mouse");
34336
34364
  };
34337
34365
  this.onMouseMove = (e) => this.onDrag(Cropper.getMousePoint(e));
34338
34366
  this.onScroll = (e) => {
@@ -34348,7 +34376,7 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34348
34376
  this.currentDoc.addEventListener("touchend", this.onDragStopped);
34349
34377
  this.saveContainerPosition();
34350
34378
  if (e.touches.length === 2) this.onPinchStart(e);
34351
- else if (e.touches.length === 1) this.onDragStart(Cropper.getTouchPoint(e.touches[0]));
34379
+ else if (e.touches.length === 1) this.onDragStart(Cropper.getTouchPoint(e.touches[0]), "touch");
34352
34380
  };
34353
34381
  this.onTouchMove = (e) => {
34354
34382
  e.preventDefault();
@@ -34377,14 +34405,15 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34377
34405
  this.onGestureEnd = (e) => {
34378
34406
  this.cleanEvents();
34379
34407
  };
34380
- this.onDragStart = ({ x, y }) => {
34408
+ this.onDragStart = ({ x, y }, source) => {
34381
34409
  var _this$props$onInterac, _this$props;
34382
34410
  this.dragStartPosition = {
34383
34411
  x,
34384
34412
  y
34385
34413
  };
34386
34414
  this.dragStartCrop = _objectSpread2({}, this.props.crop);
34387
- (_this$props$onInterac = (_this$props = this.props).onInteractionStart) === null || _this$props$onInterac === void 0 || _this$props$onInterac.call(_this$props);
34415
+ this.dragInteractionSource = source;
34416
+ (_this$props$onInterac = (_this$props = this.props).onInteractionStart) === null || _this$props$onInterac === void 0 || _this$props$onInterac.call(_this$props, { source });
34388
34417
  };
34389
34418
  this.onDrag = ({ x, y }) => {
34390
34419
  if (!this.currentWindow) return;
@@ -34403,11 +34432,12 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34403
34432
  });
34404
34433
  };
34405
34434
  this.onDragStopped = () => {
34406
- var _this$props$onInterac2, _this$props2;
34435
+ var _this$props$onInterac2, _this$props2, _this$dragInteraction;
34407
34436
  this.isTouching = false;
34408
34437
  this.cleanEvents();
34409
34438
  this.emitCropData();
34410
- (_this$props$onInterac2 = (_this$props2 = this.props).onInteractionEnd) === null || _this$props$onInterac2 === void 0 || _this$props$onInterac2.call(_this$props2);
34439
+ (_this$props$onInterac2 = (_this$props2 = this.props).onInteractionEnd) === null || _this$props$onInterac2 === void 0 || _this$props$onInterac2.call(_this$props2, { source: (_this$dragInteraction = this.dragInteractionSource) !== null && _this$dragInteraction !== void 0 ? _this$dragInteraction : "mouse" });
34440
+ this.dragInteractionSource = null;
34411
34441
  };
34412
34442
  this.onWheel = (e) => {
34413
34443
  if (!this.currentWindow) return;
@@ -34419,12 +34449,12 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34419
34449
  this.setNewZoom(newZoom, point, { shouldUpdatePosition: true });
34420
34450
  if (!this.state.hasWheelJustStarted) this.setState({ hasWheelJustStarted: true }, () => {
34421
34451
  var _this$props$onInterac3, _this$props3;
34422
- return (_this$props$onInterac3 = (_this$props3 = this.props).onInteractionStart) === null || _this$props$onInterac3 === void 0 ? void 0 : _this$props$onInterac3.call(_this$props3);
34452
+ return (_this$props$onInterac3 = (_this$props3 = this.props).onInteractionStart) === null || _this$props$onInterac3 === void 0 ? void 0 : _this$props$onInterac3.call(_this$props3, { source: "wheel" });
34423
34453
  });
34424
34454
  if (this.wheelTimer) clearTimeout(this.wheelTimer);
34425
34455
  this.wheelTimer = this.currentWindow.setTimeout(() => this.setState({ hasWheelJustStarted: false }, () => {
34426
34456
  var _this$props$onInterac4, _this$props4;
34427
- return (_this$props$onInterac4 = (_this$props4 = this.props).onInteractionEnd) === null || _this$props$onInterac4 === void 0 ? void 0 : _this$props$onInterac4.call(_this$props4);
34457
+ return (_this$props$onInterac4 = (_this$props4 = this.props).onInteractionEnd) === null || _this$props$onInterac4 === void 0 ? void 0 : _this$props$onInterac4.call(_this$props4, { source: "wheel" });
34428
34458
  }), 250);
34429
34459
  };
34430
34460
  this.getPointOnContainer = ({ x, y }, containerTopLeft) => {
@@ -34532,7 +34562,7 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34532
34562
  if (this.props.restrictPosition) newCrop = restrictPosition(newCrop, this.mediaSize, this.state.cropSize, zoom, rotation);
34533
34563
  if (!event.repeat) {
34534
34564
  var _this$props$onInterac5, _this$props5;
34535
- (_this$props$onInterac5 = (_this$props5 = this.props).onInteractionStart) === null || _this$props$onInterac5 === void 0 || _this$props$onInterac5.call(_this$props5);
34565
+ (_this$props$onInterac5 = (_this$props5 = this.props).onInteractionStart) === null || _this$props$onInterac5 === void 0 || _this$props$onInterac5.call(_this$props5, { source: "keyboard" });
34536
34566
  }
34537
34567
  onCropChange(newCrop);
34538
34568
  };
@@ -34548,7 +34578,7 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34548
34578
  default: return;
34549
34579
  }
34550
34580
  this.emitCropData();
34551
- (_this$props$onInterac6 = (_this$props6 = this.props).onInteractionEnd) === null || _this$props$onInterac6 === void 0 || _this$props$onInterac6.call(_this$props6);
34581
+ (_this$props$onInterac6 = (_this$props6 = this.props).onInteractionEnd) === null || _this$props$onInterac6 === void 0 || _this$props$onInterac6.call(_this$props6, { source: "keyboard" });
34552
34582
  };
34553
34583
  }
34554
34584
  componentDidMount() {
@@ -34628,7 +34658,7 @@ var Cropper$1 = class Cropper extends React__namespace.Component {
34628
34658
  const pointB = Cropper.getTouchPoint(e.touches[1]);
34629
34659
  this.lastPinchDistance = getDistanceBetweenPoints(pointA, pointB);
34630
34660
  this.lastPinchRotation = getRotationBetweenPoints(pointA, pointB);
34631
- this.onDragStart(getCenter(pointA, pointB));
34661
+ this.onDragStart(getCenter(pointA, pointB), "touch");
34632
34662
  }
34633
34663
  onPinchMove(e) {
34634
34664
  if (!this.currentDoc || !this.currentWindow) return;
@@ -35147,6 +35177,12 @@ const TagList = ({ items, maxVisible = DEFAULT_MAX, showMoreLabel, showLessLabel
35147
35177
  return (jsxRuntime.jsxs("div", { className: cn("flex flex-wrap items-center gap-2", className), children: [visible.map((label, i) => renderTag ? (renderTag(label, i)) : (jsxRuntime.jsx(Tag, { label: label, variant: variant }, i))), hasMore && !expanded && (jsxRuntime.jsx("span", { className: "text-sm text-gray-400", children: "..." })), hasMore && (jsxRuntime.jsx("button", { onClick: handleToggle, className: "text-xs text-ews-primary hover:underline", children: expanded ? showLessLabel : showMoreLabel }))] }));
35148
35178
  };
35149
35179
 
35180
+ /**
35181
+ * Full-width payment reminder banner (red gradient) used above the app
35182
+ * content when a licence payment is due soon or overdue.
35183
+ */
35184
+ const PaymentDueBanner = ({ title, subtitle, warning, ctaLabel, onCtaClick, onDismiss, dismissLabel = "Close", }) => (jsxRuntime.jsx("div", { "data-testid": "payment-banner", className: "overflow-hidden bg-gradient-to-r from-red-600 to-red-700 shadow-lg", children: jsxRuntime.jsx("div", { className: "px-6 py-8 sm:px-8", children: jsxRuntime.jsxs("div", { className: "flex flex-col space-y-6 sm:flex-row sm:items-center sm:justify-between sm:space-y-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center space-x-4", children: [jsxRuntime.jsx(TriangleAlert, { className: "w-8 h-8 text-white shrink-0" }), jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntime.jsx("h3", { className: "text-2xl font-bold text-white", children: title }), subtitle && (jsxRuntime.jsx("p", { className: "mt-2 text-base text-red-100", children: subtitle })), warning && (jsxRuntime.jsx("p", { className: "mt-1 text-sm font-medium text-red-200", children: warning }))] })] }), jsxRuntime.jsxs("div", { className: "flex flex-col flex-shrink-0 gap-3 sm:flex-row sm:gap-4 sm:items-center", children: [jsxRuntime.jsx("button", { onClick: onCtaClick, className: "w-full px-8 py-3 text-base font-semibold text-red-600 bg-white rounded-lg shadow-sm transition-all duration-200 sm:w-auto hover:bg-red-50 hover:shadow-md", children: ctaLabel }), onDismiss && (jsxRuntime.jsx("button", { onClick: onDismiss, className: "self-start p-2 rounded-full transition-colors bg-white/10 hover:bg-white/20 sm:self-auto", "aria-label": dismissLabel, children: jsxRuntime.jsx(X, { className: "w-5 h-5 text-white" }) }))] })] }) }) }));
35185
+
35150
35186
  const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesChange, specialties: availableSpecialties, placeholder = "Search and select medical specialties...", className = "", disabled = false, maxSelections, showSelectedCount = true, title = "Medical Specialties", label = "Select Specialties", getSelectedCountText, }) => {
35151
35187
  const [filteredSpecialties, setFilteredSpecialties] = React.useState([]);
35152
35188
  const [isLoading, setIsLoading] = React.useState(false);
@@ -39557,6 +39593,7 @@ exports.PauseOctagon = OctagonPause;
39557
39593
  exports.PauseOctagonIcon = OctagonPause;
39558
39594
  exports.PawPrint = PawPrint;
39559
39595
  exports.PawPrintIcon = PawPrint;
39596
+ exports.PaymentDueBanner = PaymentDueBanner;
39560
39597
  exports.PcCase = PcCase;
39561
39598
  exports.PcCaseIcon = PcCase;
39562
39599
  exports.Pen = Pen;
@@ -40808,6 +40845,7 @@ exports.getRegionOptions = getRegionOptions;
40808
40845
  exports.getRegionsByCountry = getRegionsByCountry;
40809
40846
  exports.icons = index;
40810
40847
  exports.isValidPhoneNumber = isValidPhoneNumber;
40848
+ exports.parseDateSafe = parseDateSafe;
40811
40849
  exports.useDebounce = useDebounce;
40812
40850
  exports.useDebouncedCallback = useDebouncedCallback;
40813
40851
  exports.useSelectField = useSelectField;