@emblemvault/hustle-react 1.1.2 → 1.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/dist/index.d.cts CHANGED
@@ -1,11 +1,12 @@
1
1
  export { HustleProvider, useHustle } from './providers/index.cjs';
2
- export { HustleChat, HustleChatProps, MarkdownContent } from './components/index.cjs';
2
+ export { HustleChat, HustleChatProps, HustleChatWidget, HustleChatWidgetConfig, HustleChatWidgetProps, MarkdownContent, WidgetPosition, WidgetSize } from './components/index.cjs';
3
3
  export { A as Attachment, C as ChatMessage, b as ChatOptions, d as ChatResponse, H as HustleConfig, h as HustleContextValue, i as HustleProviderProps, M as Model, c as StreamChunk, g as StreamEndEvent, S as StreamOptions, T as ToolCall, f as ToolEndEvent, a as ToolResult, e as ToolStartEvent } from './hustle-S48t4lTZ.cjs';
4
4
  import { S as StoredPlugin, H as HustlePlugin, a as HydratedPlugin } from './plugin-COr42J6-.cjs';
5
5
  export { C as ClientToolDefinition, E as ErrorContext, d as HustleRequest, J as JSONSchema, b as JSONSchemaProperty, e as PluginHooks, P as ProcessedResponse, f as SerializedHooks, c as SerializedToolDefinition, T as ToolExecutor } from './plugin-COr42J6-.cjs';
6
6
  export { UsePluginsReturn, usePlugins } from './hooks/index.cjs';
7
7
  export { AvailablePlugin, availablePlugins, getAvailablePlugin, migrateFunPlugin, predictionMarketPlugin } from './plugins/index.cjs';
8
8
  import 'react/jsx-runtime';
9
+ import 'react';
9
10
  import 'hustle-incognito';
10
11
 
11
12
  /**
package/dist/index.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  export { HustleProvider, useHustle } from './providers/index.js';
2
- export { HustleChat, HustleChatProps, MarkdownContent } from './components/index.js';
2
+ export { HustleChat, HustleChatProps, HustleChatWidget, HustleChatWidgetConfig, HustleChatWidgetProps, MarkdownContent, WidgetPosition, WidgetSize } from './components/index.js';
3
3
  export { A as Attachment, C as ChatMessage, b as ChatOptions, d as ChatResponse, H as HustleConfig, h as HustleContextValue, i as HustleProviderProps, M as Model, c as StreamChunk, g as StreamEndEvent, S as StreamOptions, T as ToolCall, f as ToolEndEvent, a as ToolResult, e as ToolStartEvent } from './hustle-S48t4lTZ.js';
4
4
  import { S as StoredPlugin, H as HustlePlugin, a as HydratedPlugin } from './plugin-COr42J6-.js';
5
5
  export { C as ClientToolDefinition, E as ErrorContext, d as HustleRequest, J as JSONSchema, b as JSONSchemaProperty, e as PluginHooks, P as ProcessedResponse, f as SerializedHooks, c as SerializedToolDefinition, T as ToolExecutor } from './plugin-COr42J6-.js';
6
6
  export { UsePluginsReturn, usePlugins } from './hooks/index.js';
7
7
  export { AvailablePlugin, availablePlugins, getAvailablePlugin, migrateFunPlugin, predictionMarketPlugin } from './plugins/index.js';
8
8
  import 'react/jsx-runtime';
9
+ import 'react';
9
10
  import 'hustle-incognito';
10
11
 
11
12
  /**
package/dist/index.js CHANGED
@@ -3064,6 +3064,14 @@ var animations = `
3064
3064
  text-shadow: 0 0 8px ${defaults.colors.accentPrimary};
3065
3065
  }
3066
3066
  }
3067
+ /* Hide scrollbar while maintaining scroll functionality */
3068
+ .hustle-hide-scrollbar {
3069
+ -ms-overflow-style: none; /* IE and Edge */
3070
+ scrollbar-width: none; /* Firefox */
3071
+ }
3072
+ .hustle-hide-scrollbar::-webkit-scrollbar {
3073
+ display: none; /* Chrome, Safari, Opera */
3074
+ }
3067
3075
  `;
3068
3076
  hljs.registerLanguage("javascript", javascript);
3069
3077
  hljs.registerLanguage("js", javascript);
@@ -3916,6 +3924,7 @@ function HustleChat({
3916
3924
  placeholder = "Type a message...",
3917
3925
  showSettings = false,
3918
3926
  showDebug = false,
3927
+ hideHeader = false,
3919
3928
  initialSystemPrompt = "",
3920
3929
  onMessage,
3921
3930
  onToolCall,
@@ -4079,7 +4088,7 @@ function HustleChat({
4079
4088
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4080
4089
  /* @__PURE__ */ jsx("style", { children: animations }),
4081
4090
  /* @__PURE__ */ jsxs("div", { className, style: styles.container, children: [
4082
- /* @__PURE__ */ jsxs("div", { style: styles.header, children: [
4091
+ !hideHeader && /* @__PURE__ */ jsxs("div", { style: styles.header, children: [
4083
4092
  /* @__PURE__ */ jsx("h2", { style: styles.headerTitle, children: "Chat" }),
4084
4093
  /* @__PURE__ */ jsxs("div", { style: styles.headerActions, children: [
4085
4094
  selectedModel && /* @__PURE__ */ jsx("span", { style: { fontSize: tokens.typography.fontSizeSm, color: tokens.colors.textSecondary }, children: selectedModel.split("/").pop() }),
@@ -4254,7 +4263,7 @@ function HustleChat({
4254
4263
  ] })
4255
4264
  ] })
4256
4265
  ] }) }),
4257
- /* @__PURE__ */ jsxs("div", { style: styles.messagesArea, children: [
4266
+ /* @__PURE__ */ jsxs("div", { className: "hustle-hide-scrollbar", style: styles.messagesArea, children: [
4258
4267
  messages.length === 0 && /* @__PURE__ */ jsx("div", { style: styles.messagesEmpty, children: /* @__PURE__ */ jsx("p", { children: getPlaceholderMessage() }) }),
4259
4268
  /* @__PURE__ */ jsx("div", { style: styles.messagesContainer, children: messages.map((message) => /* @__PURE__ */ jsx(
4260
4269
  MessageBubble,
@@ -4381,6 +4390,343 @@ function SettingsIcon() {
4381
4390
  function AttachIcon() {
4382
4391
  return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
4383
4392
  }
4393
+ var sizeConfigs = {
4394
+ sm: { width: "320px", height: "400px" },
4395
+ md: { width: "380px", height: "520px" },
4396
+ lg: { width: "420px", height: "600px" },
4397
+ xl: { width: "480px", height: "700px" },
4398
+ full: { width: "100vw", height: "100vh" }
4399
+ };
4400
+ var widgetStyles = {
4401
+ // Container for absolute positioning
4402
+ container: {
4403
+ position: "fixed",
4404
+ zIndex: 9999,
4405
+ fontFamily: tokens.typography.fontFamily
4406
+ },
4407
+ // Launcher button
4408
+ launcher: {
4409
+ width: "56px",
4410
+ height: "56px",
4411
+ borderRadius: tokens.radius.full,
4412
+ background: `linear-gradient(135deg, ${tokens.colors.accentPrimary} 0%, #2d7dd2 100%)`,
4413
+ border: "none",
4414
+ cursor: "pointer",
4415
+ display: "flex",
4416
+ alignItems: "center",
4417
+ justifyContent: "center",
4418
+ boxShadow: `0 4px 20px rgba(76, 154, 255, 0.4), 0 2px 8px rgba(0, 0, 0, 0.3)`,
4419
+ transition: `all ${tokens.transitions.normal}`,
4420
+ color: tokens.colors.textInverse
4421
+ },
4422
+ launcherHover: {
4423
+ transform: "scale(1.05)",
4424
+ boxShadow: `0 6px 24px rgba(76, 154, 255, 0.5), 0 4px 12px rgba(0, 0, 0, 0.4)`
4425
+ },
4426
+ // Badge
4427
+ badge: {
4428
+ position: "absolute",
4429
+ top: "-4px",
4430
+ right: "-4px",
4431
+ minWidth: "20px",
4432
+ height: "20px",
4433
+ borderRadius: tokens.radius.pill,
4434
+ background: tokens.colors.accentError,
4435
+ color: tokens.colors.textInverse,
4436
+ fontSize: tokens.typography.fontSizeXs,
4437
+ fontWeight: tokens.typography.fontWeightSemibold,
4438
+ display: "flex",
4439
+ alignItems: "center",
4440
+ justifyContent: "center",
4441
+ padding: "0 6px",
4442
+ border: `2px solid ${tokens.colors.bgPrimary}`
4443
+ },
4444
+ // Chat panel
4445
+ panel: {
4446
+ position: "absolute",
4447
+ borderRadius: tokens.radius.xl,
4448
+ background: tokens.colors.bgSecondary,
4449
+ border: `1px solid ${tokens.colors.borderPrimary}`,
4450
+ boxShadow: `0 16px 48px rgba(0, 0, 0, 0.5)`,
4451
+ overflow: "hidden",
4452
+ display: "flex",
4453
+ flexDirection: "column",
4454
+ transition: `all ${tokens.transitions.slow}`
4455
+ },
4456
+ panelHidden: {
4457
+ opacity: 0,
4458
+ transform: "scale(0.95) translateY(10px)",
4459
+ pointerEvents: "none"
4460
+ },
4461
+ panelVisible: {
4462
+ opacity: 1,
4463
+ transform: "scale(1) translateY(0)"
4464
+ },
4465
+ // Full screen mode overrides
4466
+ panelFull: {
4467
+ position: "fixed",
4468
+ top: 0,
4469
+ left: 0,
4470
+ right: 0,
4471
+ bottom: 0,
4472
+ borderRadius: 0,
4473
+ width: "100vw",
4474
+ height: "100vh"
4475
+ },
4476
+ // Close button in panel header
4477
+ closeBtn: {
4478
+ width: "32px",
4479
+ height: "32px",
4480
+ borderRadius: tokens.radius.md,
4481
+ background: "transparent",
4482
+ border: "none",
4483
+ color: tokens.colors.textTertiary,
4484
+ cursor: "pointer",
4485
+ display: "flex",
4486
+ alignItems: "center",
4487
+ justifyContent: "center",
4488
+ transition: `all ${tokens.transitions.fast}`
4489
+ },
4490
+ closeBtnHover: {
4491
+ background: tokens.colors.bgTertiary,
4492
+ color: tokens.colors.textPrimary
4493
+ }
4494
+ };
4495
+ function ChatIcon() {
4496
+ return /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
4497
+ }
4498
+ function CloseIcon() {
4499
+ return /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4500
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
4501
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
4502
+ ] });
4503
+ }
4504
+ function MinimizeIcon() {
4505
+ return /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4506
+ /* @__PURE__ */ jsx("polyline", { points: "4 14 10 14 10 20" }),
4507
+ /* @__PURE__ */ jsx("polyline", { points: "20 10 14 10 14 4" }),
4508
+ /* @__PURE__ */ jsx("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
4509
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
4510
+ ] });
4511
+ }
4512
+ function HustleChatWidget({
4513
+ config = {},
4514
+ ...chatProps
4515
+ }) {
4516
+ const {
4517
+ position = "bottom-right",
4518
+ size = "md",
4519
+ title = "Chat",
4520
+ defaultOpen = false,
4521
+ launcherIcon,
4522
+ offset = { x: 24, y: 24 },
4523
+ zIndex = 9999,
4524
+ showBadge = false,
4525
+ badgeContent,
4526
+ launcherStyle,
4527
+ panelStyle,
4528
+ onOpen,
4529
+ onClose,
4530
+ storageKey = "hustle-widget-open"
4531
+ } = config;
4532
+ const [isOpen, setIsOpen] = useState(false);
4533
+ const [isHovered, setIsHovered] = useState(false);
4534
+ const [closeHovered, setCloseHovered] = useState(false);
4535
+ const [mounted, setMounted] = useState(false);
4536
+ useEffect(() => {
4537
+ setMounted(true);
4538
+ if (storageKey && typeof window !== "undefined") {
4539
+ const stored = localStorage.getItem(storageKey);
4540
+ if (stored !== null) {
4541
+ setIsOpen(stored === "true");
4542
+ } else {
4543
+ setIsOpen(defaultOpen);
4544
+ }
4545
+ } else {
4546
+ setIsOpen(defaultOpen);
4547
+ }
4548
+ }, [defaultOpen, storageKey]);
4549
+ useEffect(() => {
4550
+ if (!mounted) return;
4551
+ if (storageKey && typeof window !== "undefined") {
4552
+ localStorage.setItem(storageKey, String(isOpen));
4553
+ }
4554
+ }, [isOpen, storageKey, mounted]);
4555
+ const toggle = useCallback(() => {
4556
+ setIsOpen((prev) => {
4557
+ const next = !prev;
4558
+ if (next) {
4559
+ onOpen?.();
4560
+ } else {
4561
+ onClose?.();
4562
+ }
4563
+ return next;
4564
+ });
4565
+ }, [onOpen, onClose]);
4566
+ const positionStyles = getPositionStyles(position, offset);
4567
+ const sizeConfig = sizeConfigs[size];
4568
+ if (!mounted) {
4569
+ return null;
4570
+ }
4571
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4572
+ /* @__PURE__ */ jsx("style", { children: animations }),
4573
+ /* @__PURE__ */ jsx("style", { children: `
4574
+ @keyframes hustle-widget-bounce {
4575
+ 0%, 100% { transform: translateY(0); }
4576
+ 50% { transform: translateY(-4px); }
4577
+ }
4578
+ ` }),
4579
+ /* @__PURE__ */ jsxs(
4580
+ "div",
4581
+ {
4582
+ style: {
4583
+ ...widgetStyles.container,
4584
+ ...positionStyles.container,
4585
+ zIndex
4586
+ },
4587
+ children: [
4588
+ /* @__PURE__ */ jsxs(
4589
+ "div",
4590
+ {
4591
+ style: {
4592
+ ...widgetStyles.panel,
4593
+ ...positionStyles.panel,
4594
+ ...size === "full" ? widgetStyles.panelFull : {
4595
+ width: sizeConfig.width,
4596
+ height: sizeConfig.height
4597
+ },
4598
+ ...isOpen ? widgetStyles.panelVisible : widgetStyles.panelHidden,
4599
+ ...panelStyle
4600
+ },
4601
+ children: [
4602
+ /* @__PURE__ */ jsxs(
4603
+ "div",
4604
+ {
4605
+ style: {
4606
+ display: "flex",
4607
+ alignItems: "center",
4608
+ justifyContent: "space-between",
4609
+ padding: `${tokens.spacing.md} ${tokens.spacing.lg}`,
4610
+ background: tokens.colors.bgPrimary,
4611
+ borderBottom: `1px solid ${tokens.colors.borderPrimary}`,
4612
+ borderRadius: `${tokens.radius.xl} ${tokens.radius.xl} 0 0`,
4613
+ flexShrink: 0
4614
+ },
4615
+ children: [
4616
+ /* @__PURE__ */ jsx(
4617
+ "span",
4618
+ {
4619
+ style: {
4620
+ fontWeight: tokens.typography.fontWeightSemibold,
4621
+ color: tokens.colors.textPrimary,
4622
+ fontSize: tokens.typography.fontSizeMd
4623
+ },
4624
+ children: title
4625
+ }
4626
+ ),
4627
+ /* @__PURE__ */ jsx(
4628
+ "button",
4629
+ {
4630
+ onClick: toggle,
4631
+ onMouseEnter: () => setCloseHovered(true),
4632
+ onMouseLeave: () => setCloseHovered(false),
4633
+ style: {
4634
+ ...widgetStyles.closeBtn,
4635
+ ...closeHovered ? widgetStyles.closeBtnHover : {}
4636
+ },
4637
+ title: "Close chat",
4638
+ children: size === "full" ? /* @__PURE__ */ jsx(MinimizeIcon, {}) : /* @__PURE__ */ jsx(CloseIcon, {})
4639
+ }
4640
+ )
4641
+ ]
4642
+ }
4643
+ ),
4644
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ jsx(HustleChatInner, { ...chatProps }) })
4645
+ ]
4646
+ }
4647
+ ),
4648
+ (size !== "full" || !isOpen) && /* @__PURE__ */ jsxs(
4649
+ "button",
4650
+ {
4651
+ onClick: toggle,
4652
+ onMouseEnter: () => setIsHovered(true),
4653
+ onMouseLeave: () => setIsHovered(false),
4654
+ style: {
4655
+ ...widgetStyles.launcher,
4656
+ ...isHovered ? widgetStyles.launcherHover : {},
4657
+ ...positionStyles.launcher,
4658
+ ...launcherStyle,
4659
+ ...isOpen ? { opacity: 0, pointerEvents: "none" } : {}
4660
+ },
4661
+ title: isOpen ? "Close chat" : "Open chat",
4662
+ "aria-label": isOpen ? "Close chat" : "Open chat",
4663
+ children: [
4664
+ launcherIcon || /* @__PURE__ */ jsx(ChatIcon, {}),
4665
+ showBadge && badgeContent && !isOpen && /* @__PURE__ */ jsx("span", { style: widgetStyles.badge, children: badgeContent })
4666
+ ]
4667
+ }
4668
+ )
4669
+ ]
4670
+ }
4671
+ )
4672
+ ] });
4673
+ }
4674
+ function HustleChatInner(props) {
4675
+ return /* @__PURE__ */ jsx(HustleChat, { ...props, hideHeader: true });
4676
+ }
4677
+ function getPositionStyles(position, offset, isOpen, size) {
4678
+ const panelGap = 16;
4679
+ switch (position) {
4680
+ case "bottom-right":
4681
+ return {
4682
+ container: {
4683
+ bottom: `${offset.y}px`,
4684
+ right: `${offset.x}px`
4685
+ },
4686
+ launcher: {},
4687
+ panel: {
4688
+ bottom: `${56 + panelGap}px`,
4689
+ right: 0
4690
+ }
4691
+ };
4692
+ case "bottom-left":
4693
+ return {
4694
+ container: {
4695
+ bottom: `${offset.y}px`,
4696
+ left: `${offset.x}px`
4697
+ },
4698
+ launcher: {},
4699
+ panel: {
4700
+ bottom: `${56 + panelGap}px`,
4701
+ left: 0
4702
+ }
4703
+ };
4704
+ case "top-right":
4705
+ return {
4706
+ container: {
4707
+ top: `${offset.y}px`,
4708
+ right: `${offset.x}px`
4709
+ },
4710
+ launcher: {},
4711
+ panel: {
4712
+ top: `${56 + panelGap}px`,
4713
+ right: 0
4714
+ }
4715
+ };
4716
+ case "top-left":
4717
+ return {
4718
+ container: {
4719
+ top: `${offset.y}px`,
4720
+ left: `${offset.x}px`
4721
+ },
4722
+ launcher: {},
4723
+ panel: {
4724
+ top: `${56 + panelGap}px`,
4725
+ left: 0
4726
+ }
4727
+ };
4728
+ }
4729
+ }
4384
4730
 
4385
4731
  // src/utils/index.ts
4386
4732
  function formatFileSize(bytes) {
@@ -4409,6 +4755,6 @@ var DEFAULTS = {
4409
4755
  EMBLEM_MODAL_URL: "https://emblemvault.ai/connect"
4410
4756
  };
4411
4757
 
4412
- export { DEFAULTS, HustleChat, HustleProvider, MarkdownContent, STORAGE_KEYS, availablePlugins, debounce, formatFileSize, getAvailablePlugin, hydratePlugin, migrateFunPlugin, pluginRegistry, predictionMarketPlugin, tokens, useHustle, usePlugins };
4758
+ export { DEFAULTS, HustleChat, HustleChatWidget, HustleProvider, MarkdownContent, STORAGE_KEYS, availablePlugins, debounce, formatFileSize, getAvailablePlugin, hydratePlugin, migrateFunPlugin, pluginRegistry, predictionMarketPlugin, tokens, useHustle, usePlugins };
4413
4759
  //# sourceMappingURL=index.js.map
4414
4760
  //# sourceMappingURL=index.js.map